re PR middle-end/13146 (inheritance for nonoverlapping_component_refs_p)
authorRichard Guenther <rguenther@suse.de>
Fri, 3 Apr 2009 10:24:28 +0000 (10:24 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Fri, 3 Apr 2009 10:24:28 +0000 (10:24 +0000)
2009-04-03  Richard Guenther  <rguenther@suse.de>

PR middle-end/13146
PR tree-optimization/23940
PR tree-optimization/33237
PR middle-end/33974
PR middle-end/34093
PR tree-optimization/36201
PR tree-optimization/36230
PR tree-optimization/38049
PR tree-optimization/38207
PR tree-optimization/38230
PR tree-optimization/38301
PR tree-optimization/38585
PR middle-end/38895
PR tree-optimization/38985
PR tree-optimization/39299
* tree-ssa-structalias.h: Remove.
* tree-ssa-operands.h (NULL_USE_OPERAND_P): Make of type use_operand_p.
(NULL_DEF_OPERAND_P): Make of type def_operand_p.
(struct vuse_element_d): Remove.
(struct vuse_vec_d): Likewise.
(VUSE_VECT_NUM_ELEM, VUSE_VECT_ELEMENT_NC, VUSE_ELEMENT_PTR_NC,
VUSE_ELEMENT_VAR_NC, VUSE_VECT_ELEMENT, VUSE_ELEMENT_PTR,
SET_VUSE_VECT_ELEMENT, SET_VUSE_ELEMENT_VAR, SET_VUSE_ELEMENT_PTR,
VUSE_ELEMENT_VAR): Likewise.
(struct voptype_d): Likewise.
(NUM_VOP_FREE_BUCKETS): Likewise.
(struct ssa_operands): Remove vop_free_buckets and mpt_table fields.
(struct stmt_operands_d): Remove.
(VUSE_OP_PTR, VUSE_OP, SET_VUSE_OP, VUSE_NUM, VUSE_VECT,
VDEF_RESULT_PTR, VDEF_RESULT, VDEF_OP_PTR, VDEF_OP, SET_VDEF_OP,
VDEF_NUM, VDEF_VECT): Likewise.
(copy_virtual_operands): Remove.
(operand_build_cmp): Likewise.
(create_ssa_artificial_load_stmt): Likewise.
(enum ssa_op_iter_type): Remove ssa_op_iter_vdef.
(struct ssa_operand_iterator_d): Remove vuses, vdefs, mayusesm
vuse_index and mayuse_index members.  Pack and move done and iter_type
members to the front.
(SSA_OP_VMAYUSE): Remove.
(SSA_OP_VIRTUAL_USES): Adjust.
(FOR_EACH_SSA_VDEF_OPERAND): Remove.
(unlink_stmt_vdef): Declare.
(add_to_addressable_set): Remove.
* tree-vrp.c (stmt_interesting_for_vrp): Adjust.
(vrp_visit_stmt): Likewise.
* doc/tree-ssa.texi (Alias analysis): Update.
* doc/invoke.texi (max-aliased-vops): Remove docs.
(avg-aliased-vops): Likewise.
* tree-into-ssa.c (syms_to_rename): Remove.
(need_to_update_vops_p): Likewise.
(need_to_initialize_update_ssa_p): Rename to ...
(update_ssa_initialized_fn): ... this.  Track function we are
initialized for.
(symbol_marked_for_renaming): Simplify.
(add_new_name_mapping): Do not set need_to_update_vops_p.
(dump_currdefs): Use SYMS_TO_RENAME.
(rewrite_update_stmt): Always walk all uses/defs.
(dump_update_ssa): Adjust.
(init_update_ssa): Take function argument.  Track what we are
initialized for.
(delete_update_ssa): Reset SYMS_TO_RENAME and update_ssa_initialized_fn.
(create_new_def_for): Initialize for cfun, assert we are initialized
for cfun.
(mark_sym_for_renaming): Simplify.
(mark_set_for_renaming): Do not initialize update-ssa.
(need_ssa_update_p): Simplify.  Take function argument.
(name_mappings_registered_p): Assert we ask for the correct function.
(name_registered_for_update_p): Likewise.
(ssa_names_to_replace): Likewise.
(release_ssa_name_after_update_ssa): Likewise.
(update_ssa): Likewise.  Use SYMS_TO_RENAME.
(dump_decl_set): Do not print a newline.
(debug_decl_set): Do it here.
(dump_update_ssa): And here.
* tree-ssa-loop-im.c (move_computations): Adjust.
(movement_possibility): Likewise.
(determine_max_movement): Likewise.
(gather_mem_refs_stmt): Likewise.
* tree-dump.c (dequeue_and_dump): Do not handle SYMBOL_MEMORY_TAG
or NAME_MEMORY_TAG.
* tree-complex.c (update_all_vops): Remove.
(expand_complex_move): Adjust.
* tree-ssa-loop-niter.c (chain_of_csts_start): Use NULL_TREE.
Simplify test for memory referencing statement.  Exclude
non-invariant ADDR_EXPRs.
* tree-pretty-print.c (dump_generic_node): Do not handle memory tags.
* tree-loop-distribution.c (generate_memset_zero): Adjust.
(rdg_flag_uses): Likewise.
* tree-tailcall.c (suitable_for_tail_opt_p): Remove memory-tag
related code.
(tree_optimize_tail_calls_1): Also split the
edge from the entry block if we have degenerate PHI nodes in
the first basic block.
* tree.c (init_ttree): Remove memory-tag related code.
(tree_code_size): Likewise.
(tree_node_structure): Likewise.
(build7_stat): Re-write to be build6_stat.
* tree.h (MTAG_P, TREE_MEMORY_TAG_CHECK, TMR_TAG): Remove.
(SSA_VAR_P): Adjust.
(struct tree_memory_tag): Remove.
(struct tree_memory_partition_tag): Likewise.
(union tree_node): Adjust.
(build7): Re-write to be build6.
* tree-pass.h (pass_reset_cc_flags): Remove.
(TODO_update_address_taken): New flag.
(pass_simple_dse): Remove.
* ipa-cp.c (ipcp_update_callgraph): Update SSA form.
* params.h (MAX_ALIASED_VOPS): Remove.
(AVG_ALIASED_VOPS): Likewise.
* omp-low.c (expand_omp_taskreg): Update SSA form.
* tree-ssa-dse.c (dse_optimize_stmt): Properly query if the rhs
aliases the lhs in a copy stmt.
* tree-ssa-dse.c (struct address_walk_data): Remove.
(memory_ssa_name_same): Likewise.
(memory_address_same): Likewise.
(get_kill_of_stmt_lhs): Likewise.
(dse_possible_dead_store_p): Simplify, use the oracle.  Handle
unused stores.  Look through PHI nodes into post-dominated regions.
(dse_optimize_stmt): Simplify.  Properly remove stores.
(tree_ssa_dse): Compute dominators.
(execute_simple_dse): Remove.
(pass_simple_dse): Likewise.
* ipa-reference.c (scan_stmt_for_static_refs): Open-code
gimple_loaded_syms and gimple_stored_syms computation.
* toplev.c (dump_memory_report): Dump alias and pta stats.
* tree-ssa-sccvn.c (vn_reference_compute_hash): Simplify.
(vn_reference_eq): Likewise.
(vuses_to_vec, copy_vuses_from_stmt, vdefs_to_vec,
copy_vdefs_from_stmt, shared_lookup_vops, shared_vuses_from_stmt,
valueize_vuses): Remove.
(get_def_ref_stmt_vuses): Simplify.  Rename to ...
(get_def_ref_stmt_vuse): ... this.
(vn_reference_lookup_2): New function.
(vn_reference_lookup_pieces): Use walk_non_aliased_vuses for
walking equivalent vuses.  Simplify.
(vn_reference_lookup): Likewise.
(vn_reference_insert): Likewise.
(vn_reference_insert_pieces): Likewise.
(visit_reference_op_call): Simplify.
(visit_reference_op_load): Likewise.
(visit_reference_op_store): Likewise.
(init_scc_vn): Remove shared_lookup_vuses initialization.
(free_scc_vn): Remove shared_lookup_vuses freeing.
(sort_vuses, sort_vuses_heap): Remove.
(get_ref_from_reference_ops): Export.
* tree-ssa-sccvn.h (struct vn_reference_s): Replace vuses
vector with single vuse pointer.
(vn_reference_lookup_pieces, vn_reference_lookup,
vn_reference_insert, vn_reference_insert_pieces): Adjust prototypes.
(shared_vuses_from_stmt): Remove.
(get_ref_from_reference_ops): Declare.
* tree-ssa-loop-manip.c (slpeel_can_duplicate_loop_p): Adjust.
* tree-ssa-copyrename.c (copy_rename_partition_coalesce): Remove
memory-tag related code.
* tree-ssa-ccp.c (get_symbol_constant_value): Remove memory-tag code.
(likely_value): Add comment, skip static-chain of call statements.
(surely_varying_stmt_p): Adjust.
(gimplify_and_update_call_from_tree): Likewise.
(execute_fold_all_builtins): Do not rebuild alias info.
(gimplify_and_update_call_from_tree): Properly update VOPs.
* tree-ssa-loop-ivopts.c (get_ref_tag): Remove.
(copy_ref_info): Remove memory-tag related code.
* tree-call-cdce.c (tree_call_cdce): Rename the VOP.
* ipa-pure-const.c (check_decl): Remove memory-tag related code.
(check_stmt): Open-code gimple_loaded_syms and gimple_stored_syms
computation.
* tree-ssa-dom.c (gimple_p): Remove typedef.
(eliminate_redundant_computations): Adjust.
(record_equivalences_from_stmt): Likewise.
(avail_expr_hash): Likewise.
(avail_expr_eq): Likewise.
* tree-ssa-propagate.c (update_call_from_tree): Properly
update VOPs.
(stmt_makes_single_load): Likewise.
(stmt_makes_single_store): Likewise.
* tree-ssa-alias.c: Rewrite completely.
(debug_memory_partitions, dump_mem_ref_stats, debug_mem_ref_stats,
debug_mem_sym_stats, dump_mem_sym_stats_for_var,
debug_all_mem_sym_stats, debug_mp_info, update_mem_sym_stats_from_stmt,
delete_mem_ref_stats, create_tag_raw, dump_points_to_info,
dump_may_aliases_for, debug_may_aliases_for, new_type_alias):
Remove public functions.
(pass_reset_cc_flags): Remove.
(pass_build_alias): Move ...
* tree-ssa-structalias.c (pass_build_alias): ... here.
* tree-ssa-alias.c (may_be_aliased): Move ...
* tree-flow-inline.h (may_be_aliased): ... here.
tree-ssa-alias.c (struct count_ptr_d, count_ptr_derefs,
count_uses_and_derefs): Move ...
* gimple.c: ... here.
* gimple.h (count_uses_and_derefs): Declare.
* tree-ssa-alias.c (dump_alias_stats, ptr_deref_may_alias_global_p,
ptr_deref_may_alias_decl_p, ptr_derefs_may_alias_p,
same_type_for_tbaa, nonaliasing_component_refs_p, decl_refs_may_alias_p,
indirect_ref_may_alias_decl_p, indirect_refs_may_alias_p,
ref_maybe_used_by_call_p, ref_maybe_used_by_stmt_p,
call_may_clobber_ref_p, stmt_may_clobber_ref_p, maybe_skip_until,
get_continuation_for_phi, walk_non_aliased_vuses, walk_aliased_vdefs):
New functions.
* tree-dfa.c (refs_may_alias_p): Move ...
* tree-ssa-alias.c (refs_may_alias_p): ... here.  Extend.
* tree-ssa-alias.h: New file.
* tree-ssa-sink.c (is_hidden_global_store): Adjust.
(statement_sink_location): Likewise.
* opts.c (decode_options): Do not adjust max-aliased-vops or
avg-aliased-vops values.
* timevar.def (TV_TREE_MAY_ALIAS): Remove.
(TV_CALL_CLOBBER): Likewise.
(TV_FLOW_SENSITIVE): Likewise.
(TV_FLOW_INSENSITIVE): Likewise.
(TV_MEMORY_PARTITIONING): Likewise.
(TV_ALIAS_STMT_WALK): New timevar.
* tree-ssa-loop-ivcanon.c (empty_loop_p): Adjust.
* tree-ssa-address.c (create_mem_ref_raw): Use build6.
(get_address_description): Remove memory-tag related code.
* tree-ssa-ifcombine.c (bb_no_side_effects_p): Adjust.
* treestruct.def (TS_MEMORY_TAG, TS_MEMORY_PARTITION_TAG): Remove.
* tree-eh.c (cleanup_empty_eh): Do not leave stale SSA_NAMEs
and immediate uses in statements.  Document.
* gimple-pretty-print.c (dump_gimple_mem_ops): Adjust.
(dump_symbols): Remove.
(dump_gimple_mem_ops): Do not dump loaded or stored syms.
* alias.c (get_deref_alias_set): New function split out from ...
(get_alias_set): ... here.
* alias.h (get_deref_alias_set): Declare.
* tree-vect-data-refs.c (vect_create_data_ref_ptr): Remove unused
type parameter.  Remove restrict pointer handling.  Create a
ref-all pointer in case type-based alias sets do not conflict.
(vect_analyze_data_refs): Remove SMT related code.
* tree-vect-stmts.c (vectorizable_store): Re-instantiate TBAA assert.
(vectorizable_load): Likewise.
* tree-data-ref.h (struct dr_alias): Remove symbol_tag field.
(DR_SYMBOL_TAG, DR_VOPS): Remove.
* tree-data-ref.c (dr_may_alias_p): Use the alias-oracle.
Ignore vops and SMTs.
(dr_analyze_alias): Likewise..
(free_data_ref): Likewise.
(create_data_ref): Likewise.
(analyze_all_data_dependences): Likewise.
(get_references_in_stmt): Adjust.
* tree-flow-inline.h (gimple_aliases_computed_p,
gimple_addressable_vars, gimple_call_clobbered_vars,
gimple_call_used_vars, gimple_global_var, may_aliases, memory_partition,
factoring_name_p, mark_call_clobbered, clear_call_clobbered,
compare_ssa_operands_equal, symbol_mem_tag, set_symbol_mem_tag,
gimple_mem_ref_stats): Remove.
(gimple_vop): New function.
(op_iter_next_use): Remove vuses and mayuses cases.
(op_iter_next_def): Remove vdefs case.
(op_iter_next_tree): Remove vuses, mayuses and vdefs cases.
(clear_and_done_ssa_iter): Do not set removed fields.
(op_iter_init): Likewise.  Skip vuse and/or vdef if requested.
Assert we are not iterating over vuses or vdefs if not also
iterating over uses or defs.
(op_iter_init_use): Likewise.
(op_iter_init_def): Likewise.
(op_iter_next_vdef): Remove.
(op_iter_next_mustdef): Likewise.
(op_iter_init_vdef): Likewise.
(compare_ssa_operands_equal): Likewise.
(link_use_stmts_after): Handle vuse operand.
(is_call_used): Use is_call_clobbered.
(is_call_clobbered): Global variables are always call clobbered,
query the call-clobbers bitmap.
(mark_call_clobbered): Ignore global variables.
(clear_call_clobbered): Likewise.
* tree-ssa-coalesce.c (create_outofssa_var_map): Adjust
virtual operands sanity check.
* tree.def (NAME_MEMORY_TAG, SYMBOL_MEMORY_TAG, MEMORY_PARTITION_TAG):
Remove.
(TARGET_MEM_REF): Remove TMR_TAG operand.
* tree-dfa.c (add_referenced_var): Initialize call-clobber state.
Remove call-clobber related code.
(remove_referenced_var): Likewise.  Do not clear mpt or symbol_mem_tag.
(dump_variable): Do not dump SMTs, memory stats, may-aliases or
partitions or escape reason.
(get_single_def_stmt, get_single_def_stmt_from_phi,
get_single_def_stmt_with_phi): Remove.
(dump_referenced_vars): Tidy.
(get_ref_base_and_extent): Allow bare decls.
(collect_dfa_stats): Adjust.
* graphite.c (rename_variables_in_stmt): Adjust.
(graphite_copy_stmts_from_block): Likewise.
(translate_clast): Likewise.
* tree-ssa-pre.c (struct bb_bitmap_sets): Add expr_dies bitmap.
(EXPR_DIES): New.
(translate_vuse_through_block): Use the oracle.
(phi_translate_1): Adjust.
(value_dies_in_block_x): Use the oracle.  Cache the outcome
in EXPR_DIES.
(valid_in_sets): Check if the VUSE for
a REFERENCE is available.
(eliminate): Do not remove stmts during elimination,
instead queue and remove them afterwards.
(do_pre): Do not rebuild alias info.
(pass_pre): Run TODO_rebuild_alias before PRE.
* tree-ssa-live.c (remove_unused_locals): Remove memory-tag code.
* tree-sra.c (sra_walk_function): Use gimple_references_memory_p.
(mark_all_v_defs_stmt): Remove.
(mark_all_v_defs_seq): Adjust.
(sra_replace): Likewise.
(scalarize_use): Likewise.
(scalarize_copy): Likewise.
(scalarize_init): Likewise.
(scalarize_ldst): Likewise.
(todoflags): Remove.
(tree_sra): Do not rebuild alias info.
(tree_sra_early): Adjust.
(pass_sra): Run TODO_update_address_taken before SRA.
* tree-predcom.c (set_alias_info): Remove.
(prepare_initializers_chain): Do not call it.
(mark_virtual_ops_for_renaming): Adjust.
(mark_virtual_ops_for_renaming_list): Remove.
(initialize_root_vars): Adjust.
(initialize_root_vars_lm): Likewise.
(prepare_initializers_chain): Likewise.
* tree-ssa-copy.c (may_propagate_copy): Remove memory-tag related code.
(may_propagate_copy_into_stmt): Likewise.
(merge_alias_info): Do nothing for now.
(propagate_tree_value_into_stmt): Adjust.
(stmt_may_generate_copy): Likewise.
* tree-ssa-forwprop.c (tidy_after_forward_propagate_addr): Do
not mark symbols for renaming.
(forward_propagate_addr_expr): Match up push/pop_stmt_changes
with the same statement, make sure to update the new pointed-to one.
* tree-ssa-dce.c (eliminate_unnecessary_stmts): Do not copy
call statements, do not mark symbols for renaming.
(mark_operand_necessary): Dump something.
(ref_may_be_aliased): New function.
(mark_aliased_reaching_defs_necessary_1): New helper function.
(mark_aliased_reaching_defs_necessary): Likewise.
(mark_all_reaching_defs_necessary_1): Likewise.
(mark_all_reaching_defs_necessary): Likewise.
(propagate_necessity): Do not process virtual PHIs.  For
non-aliased loads mark all reaching definitions as necessary.
For aliased loads and stores mark the immediate dominating
aliased clobbers as necessary.
(visited): New global static.
(perform_tree_ssa_dce): Free visited bitmap after propagating
necessity.
(remove_dead_phis): Perform simple dead virtual PHI removal.
(remove_dead_stmt): Properly unlink virtual operands when
removing stores.
(eliminate_unnecessary_stmts): Schedule PHI removal after
stmt removal.
* tree-ssa-ter.c (is_replaceable_p): Adjust.
(process_replaceable): Likewise.
(find_replaceable_in_bb): Likewise.
* tree-ssa.c (verify_ssa_name): Verify all VOPs are
based on the single gimple vop.
(verify_flow_insensitive_alias_info): Remove.
(verify_flow_sensitive_alias_info): Likewise.
(verify_call_clobbering): Likewise.
(verify_memory_partitions): Likewise.
(verify_alias_info): Likewise.
(verify_ssa): Adjust..
(execute_update_addresses_taken): Export.  Update SSA
manually.  Optimize only when optimizing.  Use a local bitmap.
(pass_update_address_taken): Remove TODO_update_ssa, add
TODO_dump_func.
(pass_update_address_taken): Just use TODO_update_address_taken.
(init_tree_ssa): Do not initialize addressable_vars.
(verify_ssa): Verify new VUSE / VDEF properties.
Verify that all stmts definitions have the stmt as SSA_NAME_DEF_STMT.
Do not call verify_alias_info.
(delete_tree_ssa): Clear the VUSE, VDEF operands.
Do not free the loaded and stored syms bitmaps.  Reset the escaped
and callused solutions.  Do not free addressable_vars.
Remove memory-tag related code.
(warn_uninitialized_var): Aliases are always available.
* tree-ssa-loop-prefetch.c (gather_memory_references): Adjust.
* lambda-code.c (can_put_in_inner_loop): Adjust.
(can_put_after_inner_loop): Likewise.
(perfect_nestify): Likewise.
* tree-vect-stmts.c (vect_stmt_relevant_p): Adjust.
(vect_gen_widened_results_half): Remove CALL_EXPR handling.
(vectorizable_conversion): Do not mark symbols for renaming.
* tree-inline.c (remap_gimple_stmt): Clear VUSE/VDEF.
(expand_call_inline): Unlink the calls virtual operands before
replacing it.
(tree_function_versioning): Do not call update_ssa if we are not
updating clones.  Simplify.
* tree-ssa-phiprop.c (phivn_valid_p): Adjust.
(propagate_with_phi): Likewise..
* tree-outof-ssa.c (create_temp): Remove memory tag and call
clobber code.  Assert we are not aliased or global.
* tree-flow.h: Include tree-ssa-alias.h
(enum escape_type): Remove.
(struct mem_sym_stats_d): Likewise.
(struct mem_ref_stats_d): Likewise.
(struct gimple_df): Add vop member.  Remove global_var,
call_clobbered_vars, call_used_vars, addressable_vars,
aliases_compted_p and mem_ref_stats members.  Add syms_to_rename,
escaped and callused members.
(struct ptr_info_def): Remove all members, add points-to solution
member pt.
(struct var_ann_d): Remove in_vuse_list, in_vdef_list,
call_clobbered, escape_mask, mpt and symbol_mem_tag members.
* Makefile.in (TREE_FLOW_H): Add tree-ssa-alias.h.
(tree-ssa-structalias.o): Remove tree-ssa-structalias.h.
(tree-ssa-alias.o): Likewise.
(toplev.o): Add tree-ssa-alias.h
(GTFILES): Remove tree-ssa-structalias.h, add tree-ssa-alias.h.
* gimple.c (gimple_set_bb): Fix off-by-one error.
(is_gimple_reg): Do not handle memory tags.
(gimple_copy): Also copy virtual operands.
Delay updating the statement.  Do not reset loaded and stored syms.
(gimple_set_stored_syms): Remove.
(gimple_set_loaded_syms): Likewise.
(gimple_call_copy_skip_args): Copy the virtual operands
and mark the new statement modified.
* tree-ssa-structalias.c (may_alias_p): Remove.
(set_uids_in_ptset): Take the alias set to prune with as
parameter.  Fold in the alias test of may_alias_p.
(compute_points_to_sets): Compute whether a ptr is dereferenced
in a local sbitmap.
(process_constraint): Deal with &ANYTHING on the lhs, reject all
other ADDRESSOF constraints on the lhs.
(get_constraint_for_component_ref): Assert that we don't get
ADDRESSOF constraints from the base of the reference.
Properly generate UNKNOWN_OFFSET for DEREF if needed.
(struct variable_info): Remove collapsed_to member.
(get_varinfo_fc): Remove.
(new_var_info): Do not set collapsed_to.
(dump_constraint): Do not follow cycles.
(dump_constraint_graph): Likewise.
(build_pred_graph): Likewise.
(build_succ_graph): Likewise.
(rewrite_constraints): Likewise.
(do_simple_structure_copy): Remove.
(do_rhs_deref_structure_copy): Remove.
(do_lhs_deref_structure_copy): Remove.
(collapse_rest_of_var): Remove.
(do_structure_copy): Re-implement.
(pta_stats): New global variable.
(dump_pta_stats): New function.
(struct constraint_expr): Make offset signed.
(UNKNOWN_OFFSET): Define special value.
(dump_constraint): Dump UNKNOWN_OFFSET as UNKNOWN.
(solution_set_expand): New helper function split out from ...
(do_sd_constraint): ... here.
(solution_set_add): Handle UNKNOWN_OFFSET.  Handle negative offsets.
(do_ds_constraint): Likewise.
(do_sd_constraint): Likewise.  Do not special-case ESCAPED = *ESCAPED
and CALLUSED = *CALLUSED.
(set_union_with_increment): Make inc argument signed.
(type_safe): Remove.
(get_constraint_for_ptr_offset): Handle unknown and negative
constant offsets.
(first_vi_for_offset): Handle offsets before start.  Bail
out early for offsets beyond the variable extent.
(first_or_preceding_vi_for_offset): New function.
(init_base_vars): Add ESCAPED = ESCAPED + UNKNOWN_OFFSET constraint.
Together with ESCAPED = *ESCAPED this properly computes reachability.
(find_what_var_points_to): New function.
(find_what_p_points_to): Implement in terms of find_what_var_points_to.
(pt_solution_reset, pt_solution_empty_p, pt_solution_includes_global,
pt_solution_includes_1, pt_solution_includes, pt_solutions_intersect_1,
pt_solutions_intersect): New functions.
(compute_call_used_vars): Remove.
(compute_may_aliases): New main entry into PTA computation.
* gimple.h (gimple_p): New typedef.
(struct gimple_statement_base): Remove references_memory_p.
(struct gimple_statement_with_memory_ops_base): Remove
vdef_ops, vuse_ops, stores and loads members.  Add vdef and vuse
members.
(gimple_vuse_ops, gimple_set_vuse_ops, gimple_vdef_ops,
gimple_set_vdef_ops, gimple_loaded_syms, gimple_stored_syms,
gimple_set_references_memory): Remove.
(gimple_vuse_op, gimple_vdef_op, gimple_vuse, gimple_vdef,
gimple_vuse_ptr, gimple_vdef_ptri, gimple_set_vuse, gimple_set_vdef):
New functions.
* tree-cfg.c (move_block_to_fn): Fix off-by-one error.
(verify_expr): Allow RESULT_DECL.
(gimple_duplicate_bb): Do not copy virtual operands.
(gimple_duplicate_sese_region): Adjust.
(gimple_duplicate_sese_tail): Likewise.
(mark_virtual_ops_in_region): Remove.
(move_sese_region_to_fn): Do not call it.
* passes.c (init_optimization_passes): Remove pass_reset_cc_flags
and pass_simple_dse.
(execute_function_todo): Handle TODO_update_address_taken,
call execute_update_addresses_taken for TODO_rebuild_alias.
(execute_todo): Adjust.
(execute_one_pass): Init dump files early.
* ipa-struct-reorg.c (finalize_var_creation): Do not mark vars
call-clobbered.
(create_general_new_stmt): Clear vops.
* tree-ssa-reassoc.c (get_rank): Adjust.
* tree-vect-slp.c (vect_create_mask_and_perm): Do not mark
symbols for renaming.
* params.def (PARAM_MAX_ALIASED_VOPS): Remove.
(PARAM_AVG_ALIASED_VOPS): Likewise.
* tree-ssanames.c (init_ssanames): Allocate SYMS_TO_RENAME.
(duplicate_ssa_name_ptr_info): No need to copy the shared bitmaps.
* tree-ssa-operands.c: Simplify for new virtual operand
representation.
(operand_build_cmp, copy_virtual_operands,
create_ssa_artificial_load_stmt, add_to_addressable_set,
gimple_add_to_addresses_taken): Remove public functions.
(unlink_stmt_vdef): New function.

* gcc.dg/pr19633-1.c: Adjust.
* gcc.dg/torture/pta-callused-1.c: Likewise.
* gcc.dg/torture/pr39074-2.c: Likewise.
* gcc.dg/torture/pr39074.c: Likewise.
* gcc.dg/torture/pta-ptrarith-3.c: New testcase.
* gcc.dg/torture/pr30375.c: Adjust.
* gcc.dg/torture/pr33563.c: Likewise.
* gcc.dg/torture/pr33870.c: Likewise.
* gcc.dg/torture/pr33560.c: Likewise.
* gcc.dg/torture/pta-structcopy-1.c: New testcase.
* gcc.dg/torture/ssa-pta-fn-1.c: Likewise.
* gcc.dg/tree-ssa/alias-15.c: Remove.
* gcc.dg/tree-ssa/ssa-dce-4.c: New testcase.
* gcc.dg/tree-ssa/pr26421.c: Adjust.
* gcc.dg/tree-ssa/ssa-fre-10.c: XFAIL.
* gcc.dg/tree-ssa/ssa-dce-5.c: New testcase.
* gcc.dg/tree-ssa/pr23382.c: Adjust.
* gcc.dg/tree-ssa/ssa-fre-20.c: New testcase.
* gcc.dg/tree-ssa/alias-16.c: Adjust.
* gcc.dg/tree-ssa/ssa-fre-13.c: Likewise.
* gcc.dg/tree-ssa/ssa-fre-14.c: Likewise.
* gcc.dg/tree-ssa/alias-18.c: Likewise.
* gcc.dg/tree-ssa/ssa-fre-15.c: Likewise.
* gcc.dg/tree-ssa/ssa-lim-3.c: Likewise.
* gcc.dg/tree-ssa/alias-19.c: Likewise.
* gcc.dg/tree-ssa/pta-ptrarith-1.c: New testcase.
* gcc.dg/tree-ssa/pr13146.c: Likewise.
* gcc.dg/tree-ssa/ssa-pre-23.c: Likewise.
* gcc.dg/tree-ssa/pta-ptrarith-2.c: Likewise.
* gcc.dg/tree-ssa/ssa-fre-18.c: Likewise.
* gcc.dg/tree-ssa/ssa-pre-24.c: New XFAILed testcase.
* gcc.dg/tree-ssa/ssa-fre-19.c: New testcase.
* gcc.dg/tree-ssa/alias-20.c: Likewise.
* gcc.dg/tree-ssa/ssa-dse-12.c: Likewise.
* gcc.dg/tree-ssa/pr38895.c: Likewise.
* gcc.dg/uninit-B.c: XFAIL.
* gcc.dg/vect/no-vfa-vect-43.c: Adjust.
* gcc.dg/uninit-pr19430.c: XFAIL.
* g++.dg/tree-ssa/pr13146.C: New testcase.
* g++.dg/opt/pr36187.C: Adjust.
* g++.dg/torture/20090329-1.C: New testcase.

From-SVN: r145494

125 files changed:
gcc/ChangeLog
gcc/Makefile.in
gcc/alias.c
gcc/alias.h
gcc/doc/invoke.texi
gcc/doc/tree-ssa.texi
gcc/gimple-pretty-print.c
gcc/gimple.c
gcc/gimple.h
gcc/graphite.c
gcc/ipa-cp.c
gcc/ipa-pure-const.c
gcc/ipa-reference.c
gcc/ipa-struct-reorg.c
gcc/lambda-code.c
gcc/omp-low.c
gcc/opts.c
gcc/params.def
gcc/params.h
gcc/passes.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/opt/pr36187.C
gcc/testsuite/g++.dg/torture/20090329-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tree-ssa/pr13146.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr19633-1.c
gcc/testsuite/gcc.dg/torture/pr30375.c
gcc/testsuite/gcc.dg/torture/pr33560.c
gcc/testsuite/gcc.dg/torture/pr33563.c
gcc/testsuite/gcc.dg/torture/pr33870.c
gcc/testsuite/gcc.dg/torture/pr39074-2.c
gcc/testsuite/gcc.dg/torture/pr39074.c
gcc/testsuite/gcc.dg/torture/pta-callused-1.c
gcc/testsuite/gcc.dg/torture/pta-ptrarith-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/pta-structcopy-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/ssa-pta-fn-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/alias-15.c [deleted file]
gcc/testsuite/gcc.dg/tree-ssa/alias-16.c
gcc/testsuite/gcc.dg/tree-ssa/alias-18.c
gcc/testsuite/gcc.dg/tree-ssa/alias-19.c
gcc/testsuite/gcc.dg/tree-ssa/alias-20.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/pr13146.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/pr23382.c
gcc/testsuite/gcc.dg/tree-ssa/pr26421.c
gcc/testsuite/gcc.dg/tree-ssa/pr38895.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/pta-ptrarith-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/pta-ptrarith-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/ssa-dce-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/ssa-dce-5.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-12.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-10.c
gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-13.c
gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-14.c
gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-15.c
gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-18.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-19.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-20.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-3.c
gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-23.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-24.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/uninit-B.c
gcc/testsuite/gcc.dg/uninit-pr19430.c
gcc/testsuite/gcc.dg/vect/no-vfa-vect-43.c
gcc/timevar.def
gcc/toplev.c
gcc/tree-call-cdce.c
gcc/tree-cfg.c
gcc/tree-complex.c
gcc/tree-data-ref.c
gcc/tree-data-ref.h
gcc/tree-dfa.c
gcc/tree-dump.c
gcc/tree-eh.c
gcc/tree-flow-inline.h
gcc/tree-flow.h
gcc/tree-inline.c
gcc/tree-into-ssa.c
gcc/tree-loop-distribution.c
gcc/tree-outof-ssa.c
gcc/tree-pass.h
gcc/tree-predcom.c
gcc/tree-pretty-print.c
gcc/tree-sra.c
gcc/tree-ssa-address.c
gcc/tree-ssa-alias.c
gcc/tree-ssa-alias.h [new file with mode: 0644]
gcc/tree-ssa-ccp.c
gcc/tree-ssa-coalesce.c
gcc/tree-ssa-copy.c
gcc/tree-ssa-copyrename.c
gcc/tree-ssa-dce.c
gcc/tree-ssa-dom.c
gcc/tree-ssa-dse.c
gcc/tree-ssa-forwprop.c
gcc/tree-ssa-ifcombine.c
gcc/tree-ssa-live.c
gcc/tree-ssa-loop-im.c
gcc/tree-ssa-loop-ivcanon.c
gcc/tree-ssa-loop-ivopts.c
gcc/tree-ssa-loop-niter.c
gcc/tree-ssa-loop-prefetch.c
gcc/tree-ssa-operands.c
gcc/tree-ssa-operands.h
gcc/tree-ssa-phiprop.c
gcc/tree-ssa-pre.c
gcc/tree-ssa-propagate.c
gcc/tree-ssa-reassoc.c
gcc/tree-ssa-sccvn.c
gcc/tree-ssa-sccvn.h
gcc/tree-ssa-sink.c
gcc/tree-ssa-structalias.c
gcc/tree-ssa-structalias.h [deleted file]
gcc/tree-ssa-ter.c
gcc/tree-ssa.c
gcc/tree-ssanames.c
gcc/tree-tailcall.c
gcc/tree-vect-data-refs.c
gcc/tree-vect-loop-manip.c
gcc/tree-vect-slp.c
gcc/tree-vect-stmts.c
gcc/tree-vectorizer.h
gcc/tree-vrp.c
gcc/tree.c
gcc/tree.def
gcc/tree.h
gcc/treestruct.def

index 7c7b7cf..3885147 100644 (file)
@@ -1,3 +1,507 @@
+2009-04-03  Richard Guenther  <rguenther@suse.de>
+
+       PR middle-end/13146
+       PR tree-optimization/23940
+       PR tree-optimization/33237
+       PR middle-end/33974
+       PR middle-end/34093
+       PR tree-optimization/36201
+       PR tree-optimization/36230
+       PR tree-optimization/38049
+       PR tree-optimization/38207
+       PR tree-optimization/38230
+       PR tree-optimization/38301
+       PR tree-optimization/38585
+       PR middle-end/38895
+       PR tree-optimization/38985
+       PR tree-optimization/39299
+       * tree-ssa-structalias.h: Remove.
+       * tree-ssa-operands.h (NULL_USE_OPERAND_P): Make of type use_operand_p.
+       (NULL_DEF_OPERAND_P): Make of type def_operand_p.
+       (struct vuse_element_d): Remove.
+       (struct vuse_vec_d): Likewise.
+       (VUSE_VECT_NUM_ELEM, VUSE_VECT_ELEMENT_NC, VUSE_ELEMENT_PTR_NC,
+       VUSE_ELEMENT_VAR_NC, VUSE_VECT_ELEMENT, VUSE_ELEMENT_PTR,
+       SET_VUSE_VECT_ELEMENT, SET_VUSE_ELEMENT_VAR, SET_VUSE_ELEMENT_PTR,
+       VUSE_ELEMENT_VAR): Likewise.
+       (struct voptype_d): Likewise.
+       (NUM_VOP_FREE_BUCKETS): Likewise.
+       (struct ssa_operands): Remove vop_free_buckets and mpt_table fields.
+       (struct stmt_operands_d): Remove.
+       (VUSE_OP_PTR, VUSE_OP, SET_VUSE_OP, VUSE_NUM, VUSE_VECT,
+       VDEF_RESULT_PTR, VDEF_RESULT, VDEF_OP_PTR, VDEF_OP, SET_VDEF_OP,
+       VDEF_NUM, VDEF_VECT): Likewise.
+       (copy_virtual_operands): Remove.
+       (operand_build_cmp): Likewise.
+       (create_ssa_artificial_load_stmt): Likewise.
+       (enum ssa_op_iter_type): Remove ssa_op_iter_vdef.
+       (struct ssa_operand_iterator_d): Remove vuses, vdefs, mayusesm
+       vuse_index and mayuse_index members.  Pack and move done and iter_type
+       members to the front.
+       (SSA_OP_VMAYUSE): Remove.
+       (SSA_OP_VIRTUAL_USES): Adjust.
+       (FOR_EACH_SSA_VDEF_OPERAND): Remove.
+       (unlink_stmt_vdef): Declare.
+       (add_to_addressable_set): Remove.
+       * tree-vrp.c (stmt_interesting_for_vrp): Adjust.
+       (vrp_visit_stmt): Likewise.
+       * doc/tree-ssa.texi (Alias analysis): Update.
+       * doc/invoke.texi (max-aliased-vops): Remove docs.
+       (avg-aliased-vops): Likewise.
+       * tree-into-ssa.c (syms_to_rename): Remove.
+       (need_to_update_vops_p): Likewise.
+       (need_to_initialize_update_ssa_p): Rename to ...
+       (update_ssa_initialized_fn): ... this.  Track function we are
+       initialized for.
+       (symbol_marked_for_renaming): Simplify.
+       (add_new_name_mapping): Do not set need_to_update_vops_p.
+       (dump_currdefs): Use SYMS_TO_RENAME.
+       (rewrite_update_stmt): Always walk all uses/defs.
+       (dump_update_ssa): Adjust.
+       (init_update_ssa): Take function argument.  Track what we are
+       initialized for.
+       (delete_update_ssa): Reset SYMS_TO_RENAME and update_ssa_initialized_fn.
+       (create_new_def_for): Initialize for cfun, assert we are initialized
+       for cfun.
+       (mark_sym_for_renaming): Simplify.
+       (mark_set_for_renaming): Do not initialize update-ssa.
+       (need_ssa_update_p): Simplify.  Take function argument.
+       (name_mappings_registered_p): Assert we ask for the correct function.
+       (name_registered_for_update_p): Likewise.
+       (ssa_names_to_replace): Likewise.
+       (release_ssa_name_after_update_ssa): Likewise.
+       (update_ssa): Likewise.  Use SYMS_TO_RENAME.
+       (dump_decl_set): Do not print a newline.
+       (debug_decl_set): Do it here.
+       (dump_update_ssa): And here.
+       * tree-ssa-loop-im.c (move_computations): Adjust.
+       (movement_possibility): Likewise.
+       (determine_max_movement): Likewise.
+       (gather_mem_refs_stmt): Likewise.
+       * tree-dump.c (dequeue_and_dump): Do not handle SYMBOL_MEMORY_TAG
+       or NAME_MEMORY_TAG.
+       * tree-complex.c (update_all_vops): Remove.
+       (expand_complex_move): Adjust.
+       * tree-ssa-loop-niter.c (chain_of_csts_start): Use NULL_TREE.
+       Simplify test for memory referencing statement.  Exclude
+       non-invariant ADDR_EXPRs.
+       * tree-pretty-print.c (dump_generic_node): Do not handle memory tags.
+       * tree-loop-distribution.c (generate_memset_zero): Adjust.
+       (rdg_flag_uses): Likewise.
+       * tree-tailcall.c (suitable_for_tail_opt_p): Remove memory-tag
+       related code.
+       (tree_optimize_tail_calls_1): Also split the
+       edge from the entry block if we have degenerate PHI nodes in
+       the first basic block.
+       * tree.c (init_ttree): Remove memory-tag related code.
+       (tree_code_size): Likewise.
+       (tree_node_structure): Likewise.
+       (build7_stat): Re-write to be build6_stat.
+       * tree.h (MTAG_P, TREE_MEMORY_TAG_CHECK, TMR_TAG): Remove.
+       (SSA_VAR_P): Adjust.
+       (struct tree_memory_tag): Remove.
+       (struct tree_memory_partition_tag): Likewise.
+       (union tree_node): Adjust.
+       (build7): Re-write to be build6.
+       * tree-pass.h (pass_reset_cc_flags): Remove.
+       (TODO_update_address_taken): New flag.
+       (pass_simple_dse): Remove.
+       * ipa-cp.c (ipcp_update_callgraph): Update SSA form.
+       * params.h (MAX_ALIASED_VOPS): Remove.
+       (AVG_ALIASED_VOPS): Likewise.
+       * omp-low.c (expand_omp_taskreg): Update SSA form.
+       * tree-ssa-dse.c (dse_optimize_stmt): Properly query if the rhs
+       aliases the lhs in a copy stmt.
+       * tree-ssa-dse.c (struct address_walk_data): Remove.
+       (memory_ssa_name_same): Likewise.
+       (memory_address_same): Likewise.
+       (get_kill_of_stmt_lhs): Likewise.
+       (dse_possible_dead_store_p): Simplify, use the oracle.  Handle
+       unused stores.  Look through PHI nodes into post-dominated regions.
+       (dse_optimize_stmt): Simplify.  Properly remove stores.
+       (tree_ssa_dse): Compute dominators.
+       (execute_simple_dse): Remove.
+       (pass_simple_dse): Likewise.
+       * ipa-reference.c (scan_stmt_for_static_refs): Open-code
+       gimple_loaded_syms and gimple_stored_syms computation.
+       * toplev.c (dump_memory_report): Dump alias and pta stats.
+       * tree-ssa-sccvn.c (vn_reference_compute_hash): Simplify.
+       (vn_reference_eq): Likewise.
+       (vuses_to_vec, copy_vuses_from_stmt, vdefs_to_vec,
+       copy_vdefs_from_stmt, shared_lookup_vops, shared_vuses_from_stmt,
+       valueize_vuses): Remove.
+       (get_def_ref_stmt_vuses): Simplify.  Rename to ...
+       (get_def_ref_stmt_vuse): ... this.
+       (vn_reference_lookup_2): New function.
+       (vn_reference_lookup_pieces): Use walk_non_aliased_vuses for
+       walking equivalent vuses.  Simplify.
+       (vn_reference_lookup): Likewise.
+       (vn_reference_insert): Likewise.
+       (vn_reference_insert_pieces): Likewise.
+       (visit_reference_op_call): Simplify.
+       (visit_reference_op_load): Likewise.
+       (visit_reference_op_store): Likewise.
+       (init_scc_vn): Remove shared_lookup_vuses initialization.
+       (free_scc_vn): Remove shared_lookup_vuses freeing.
+       (sort_vuses, sort_vuses_heap): Remove.
+       (get_ref_from_reference_ops): Export.
+       * tree-ssa-sccvn.h (struct vn_reference_s): Replace vuses
+       vector with single vuse pointer.
+       (vn_reference_lookup_pieces, vn_reference_lookup,
+       vn_reference_insert, vn_reference_insert_pieces): Adjust prototypes.
+       (shared_vuses_from_stmt): Remove.
+       (get_ref_from_reference_ops): Declare.
+       * tree-ssa-loop-manip.c (slpeel_can_duplicate_loop_p): Adjust.
+       * tree-ssa-copyrename.c (copy_rename_partition_coalesce): Remove
+       memory-tag related code.
+       * tree-ssa-ccp.c (get_symbol_constant_value): Remove memory-tag code.
+       (likely_value): Add comment, skip static-chain of call statements.
+       (surely_varying_stmt_p): Adjust.
+       (gimplify_and_update_call_from_tree): Likewise.
+       (execute_fold_all_builtins): Do not rebuild alias info.
+       (gimplify_and_update_call_from_tree): Properly update VOPs.
+       * tree-ssa-loop-ivopts.c (get_ref_tag): Remove.
+       (copy_ref_info): Remove memory-tag related code.
+       * tree-call-cdce.c (tree_call_cdce): Rename the VOP.
+       * ipa-pure-const.c (check_decl): Remove memory-tag related code.
+       (check_stmt): Open-code gimple_loaded_syms and gimple_stored_syms
+       computation.
+       * tree-ssa-dom.c (gimple_p): Remove typedef.
+       (eliminate_redundant_computations): Adjust.
+       (record_equivalences_from_stmt): Likewise.
+       (avail_expr_hash): Likewise.
+       (avail_expr_eq): Likewise.
+       * tree-ssa-propagate.c (update_call_from_tree): Properly
+       update VOPs.
+       (stmt_makes_single_load): Likewise.
+       (stmt_makes_single_store): Likewise.
+       * tree-ssa-alias.c: Rewrite completely.
+       (debug_memory_partitions, dump_mem_ref_stats, debug_mem_ref_stats,
+       debug_mem_sym_stats, dump_mem_sym_stats_for_var,
+       debug_all_mem_sym_stats, debug_mp_info, update_mem_sym_stats_from_stmt,
+       delete_mem_ref_stats, create_tag_raw, dump_points_to_info,
+       dump_may_aliases_for, debug_may_aliases_for, new_type_alias):
+       Remove public functions.
+       (pass_reset_cc_flags): Remove.
+       (pass_build_alias): Move ...
+       * tree-ssa-structalias.c (pass_build_alias): ... here.
+       * tree-ssa-alias.c (may_be_aliased): Move ...
+       * tree-flow-inline.h (may_be_aliased): ... here.
+       tree-ssa-alias.c (struct count_ptr_d, count_ptr_derefs,
+       count_uses_and_derefs): Move ...
+       * gimple.c: ... here.
+       * gimple.h (count_uses_and_derefs): Declare.
+       * tree-ssa-alias.c (dump_alias_stats, ptr_deref_may_alias_global_p,
+       ptr_deref_may_alias_decl_p, ptr_derefs_may_alias_p,
+       same_type_for_tbaa, nonaliasing_component_refs_p, decl_refs_may_alias_p,
+       indirect_ref_may_alias_decl_p, indirect_refs_may_alias_p,
+       ref_maybe_used_by_call_p, ref_maybe_used_by_stmt_p,
+       call_may_clobber_ref_p, stmt_may_clobber_ref_p, maybe_skip_until,
+       get_continuation_for_phi, walk_non_aliased_vuses, walk_aliased_vdefs):
+       New functions.
+       * tree-dfa.c (refs_may_alias_p): Move ...
+       * tree-ssa-alias.c (refs_may_alias_p): ... here.  Extend.
+       * tree-ssa-alias.h: New file.
+       * tree-ssa-sink.c (is_hidden_global_store): Adjust.
+       (statement_sink_location): Likewise.
+       * opts.c (decode_options): Do not adjust max-aliased-vops or
+       avg-aliased-vops values.
+       * timevar.def (TV_TREE_MAY_ALIAS): Remove.
+       (TV_CALL_CLOBBER): Likewise.
+       (TV_FLOW_SENSITIVE): Likewise.
+       (TV_FLOW_INSENSITIVE): Likewise.
+       (TV_MEMORY_PARTITIONING): Likewise.
+       (TV_ALIAS_STMT_WALK): New timevar.
+       * tree-ssa-loop-ivcanon.c (empty_loop_p): Adjust.
+       * tree-ssa-address.c (create_mem_ref_raw): Use build6.
+       (get_address_description): Remove memory-tag related code.
+       * tree-ssa-ifcombine.c (bb_no_side_effects_p): Adjust.
+       * treestruct.def (TS_MEMORY_TAG, TS_MEMORY_PARTITION_TAG): Remove.
+       * tree-eh.c (cleanup_empty_eh): Do not leave stale SSA_NAMEs
+       and immediate uses in statements.  Document.
+       * gimple-pretty-print.c (dump_gimple_mem_ops): Adjust.
+       (dump_symbols): Remove.
+       (dump_gimple_mem_ops): Do not dump loaded or stored syms.
+       * alias.c (get_deref_alias_set): New function split out from ...
+       (get_alias_set): ... here.
+       * alias.h (get_deref_alias_set): Declare.
+       * tree-vect-data-refs.c (vect_create_data_ref_ptr): Remove unused
+       type parameter.  Remove restrict pointer handling.  Create a
+       ref-all pointer in case type-based alias sets do not conflict.
+       (vect_analyze_data_refs): Remove SMT related code.
+       * tree-vect-stmts.c (vectorizable_store): Re-instantiate TBAA assert.
+       (vectorizable_load): Likewise.
+       * tree-data-ref.h (struct dr_alias): Remove symbol_tag field.
+       (DR_SYMBOL_TAG, DR_VOPS): Remove.
+       * tree-data-ref.c (dr_may_alias_p): Use the alias-oracle.
+       Ignore vops and SMTs.
+       (dr_analyze_alias): Likewise..
+       (free_data_ref): Likewise.
+       (create_data_ref): Likewise.
+       (analyze_all_data_dependences): Likewise.
+       (get_references_in_stmt): Adjust.
+       * tree-flow-inline.h (gimple_aliases_computed_p,
+       gimple_addressable_vars, gimple_call_clobbered_vars,
+       gimple_call_used_vars, gimple_global_var, may_aliases, memory_partition,
+       factoring_name_p, mark_call_clobbered, clear_call_clobbered,
+       compare_ssa_operands_equal, symbol_mem_tag, set_symbol_mem_tag,
+       gimple_mem_ref_stats): Remove.
+       (gimple_vop): New function.
+       (op_iter_next_use): Remove vuses and mayuses cases.
+       (op_iter_next_def): Remove vdefs case.
+       (op_iter_next_tree): Remove vuses, mayuses and vdefs cases.
+       (clear_and_done_ssa_iter): Do not set removed fields.
+       (op_iter_init): Likewise.  Skip vuse and/or vdef if requested.
+       Assert we are not iterating over vuses or vdefs if not also
+       iterating over uses or defs.
+       (op_iter_init_use): Likewise.
+       (op_iter_init_def): Likewise.
+       (op_iter_next_vdef): Remove.
+       (op_iter_next_mustdef): Likewise.
+       (op_iter_init_vdef): Likewise.
+       (compare_ssa_operands_equal): Likewise.
+       (link_use_stmts_after): Handle vuse operand.
+       (is_call_used): Use is_call_clobbered.
+       (is_call_clobbered): Global variables are always call clobbered,
+       query the call-clobbers bitmap.
+       (mark_call_clobbered): Ignore global variables.
+       (clear_call_clobbered): Likewise.
+       * tree-ssa-coalesce.c (create_outofssa_var_map): Adjust
+       virtual operands sanity check.
+       * tree.def (NAME_MEMORY_TAG, SYMBOL_MEMORY_TAG, MEMORY_PARTITION_TAG):
+       Remove.
+       (TARGET_MEM_REF): Remove TMR_TAG operand.
+       * tree-dfa.c (add_referenced_var): Initialize call-clobber state.
+       Remove call-clobber related code.
+       (remove_referenced_var): Likewise.  Do not clear mpt or symbol_mem_tag.
+       (dump_variable): Do not dump SMTs, memory stats, may-aliases or
+       partitions or escape reason.
+       (get_single_def_stmt, get_single_def_stmt_from_phi,
+       get_single_def_stmt_with_phi): Remove.
+       (dump_referenced_vars): Tidy.
+       (get_ref_base_and_extent): Allow bare decls.
+       (collect_dfa_stats): Adjust.
+       * graphite.c (rename_variables_in_stmt): Adjust.
+       (graphite_copy_stmts_from_block): Likewise.
+       (translate_clast): Likewise.
+       * tree-ssa-pre.c (struct bb_bitmap_sets): Add expr_dies bitmap.
+       (EXPR_DIES): New.
+       (translate_vuse_through_block): Use the oracle.
+       (phi_translate_1): Adjust.
+       (value_dies_in_block_x): Use the oracle.  Cache the outcome
+       in EXPR_DIES.
+       (valid_in_sets): Check if the VUSE for
+       a REFERENCE is available.
+       (eliminate): Do not remove stmts during elimination,
+       instead queue and remove them afterwards.
+       (do_pre): Do not rebuild alias info.
+       (pass_pre): Run TODO_rebuild_alias before PRE.
+       * tree-ssa-live.c (remove_unused_locals): Remove memory-tag code.
+       * tree-sra.c (sra_walk_function): Use gimple_references_memory_p.
+       (mark_all_v_defs_stmt): Remove.
+       (mark_all_v_defs_seq): Adjust.
+       (sra_replace): Likewise.
+       (scalarize_use): Likewise.
+       (scalarize_copy): Likewise.
+       (scalarize_init): Likewise.
+       (scalarize_ldst): Likewise.
+       (todoflags): Remove.
+       (tree_sra): Do not rebuild alias info.
+       (tree_sra_early): Adjust.
+       (pass_sra): Run TODO_update_address_taken before SRA.
+       * tree-predcom.c (set_alias_info): Remove.
+       (prepare_initializers_chain): Do not call it.
+       (mark_virtual_ops_for_renaming): Adjust.
+       (mark_virtual_ops_for_renaming_list): Remove.
+       (initialize_root_vars): Adjust.
+       (initialize_root_vars_lm): Likewise.
+       (prepare_initializers_chain): Likewise.
+       * tree-ssa-copy.c (may_propagate_copy): Remove memory-tag related code.
+       (may_propagate_copy_into_stmt): Likewise.
+       (merge_alias_info): Do nothing for now.
+       (propagate_tree_value_into_stmt): Adjust.
+       (stmt_may_generate_copy): Likewise.
+       * tree-ssa-forwprop.c (tidy_after_forward_propagate_addr): Do
+       not mark symbols for renaming.
+       (forward_propagate_addr_expr): Match up push/pop_stmt_changes
+       with the same statement, make sure to update the new pointed-to one.
+       * tree-ssa-dce.c (eliminate_unnecessary_stmts): Do not copy
+       call statements, do not mark symbols for renaming.
+       (mark_operand_necessary): Dump something.
+       (ref_may_be_aliased): New function.
+       (mark_aliased_reaching_defs_necessary_1): New helper function.
+       (mark_aliased_reaching_defs_necessary): Likewise.
+       (mark_all_reaching_defs_necessary_1): Likewise.
+       (mark_all_reaching_defs_necessary): Likewise.
+       (propagate_necessity): Do not process virtual PHIs.  For
+       non-aliased loads mark all reaching definitions as necessary.
+       For aliased loads and stores mark the immediate dominating
+       aliased clobbers as necessary.
+       (visited): New global static.
+       (perform_tree_ssa_dce): Free visited bitmap after propagating
+       necessity.
+       (remove_dead_phis): Perform simple dead virtual PHI removal.
+       (remove_dead_stmt): Properly unlink virtual operands when
+       removing stores.
+       (eliminate_unnecessary_stmts): Schedule PHI removal after
+       stmt removal.
+       * tree-ssa-ter.c (is_replaceable_p): Adjust.
+       (process_replaceable): Likewise.
+       (find_replaceable_in_bb): Likewise.
+       * tree-ssa.c (verify_ssa_name): Verify all VOPs are
+       based on the single gimple vop.
+       (verify_flow_insensitive_alias_info): Remove.
+       (verify_flow_sensitive_alias_info): Likewise.
+       (verify_call_clobbering): Likewise.
+       (verify_memory_partitions): Likewise.
+       (verify_alias_info): Likewise.
+       (verify_ssa): Adjust..
+       (execute_update_addresses_taken): Export.  Update SSA
+       manually.  Optimize only when optimizing.  Use a local bitmap.
+       (pass_update_address_taken): Remove TODO_update_ssa, add
+       TODO_dump_func.
+       (pass_update_address_taken): Just use TODO_update_address_taken.
+       (init_tree_ssa): Do not initialize addressable_vars.
+       (verify_ssa): Verify new VUSE / VDEF properties.
+       Verify that all stmts definitions have the stmt as SSA_NAME_DEF_STMT.
+       Do not call verify_alias_info.
+       (delete_tree_ssa): Clear the VUSE, VDEF operands.
+       Do not free the loaded and stored syms bitmaps.  Reset the escaped
+       and callused solutions.  Do not free addressable_vars.
+       Remove memory-tag related code.
+       (warn_uninitialized_var): Aliases are always available.
+       * tree-ssa-loop-prefetch.c (gather_memory_references): Adjust.
+       * lambda-code.c (can_put_in_inner_loop): Adjust.
+       (can_put_after_inner_loop): Likewise.
+       (perfect_nestify): Likewise.
+       * tree-vect-stmts.c (vect_stmt_relevant_p): Adjust.
+       (vect_gen_widened_results_half): Remove CALL_EXPR handling.
+       (vectorizable_conversion): Do not mark symbols for renaming.
+       * tree-inline.c (remap_gimple_stmt): Clear VUSE/VDEF.
+       (expand_call_inline): Unlink the calls virtual operands before
+       replacing it.
+       (tree_function_versioning): Do not call update_ssa if we are not
+       updating clones.  Simplify.
+       * tree-ssa-phiprop.c (phivn_valid_p): Adjust.
+       (propagate_with_phi): Likewise..
+       * tree-outof-ssa.c (create_temp): Remove memory tag and call
+       clobber code.  Assert we are not aliased or global.
+       * tree-flow.h: Include tree-ssa-alias.h
+       (enum escape_type): Remove.
+       (struct mem_sym_stats_d): Likewise.
+       (struct mem_ref_stats_d): Likewise.
+       (struct gimple_df): Add vop member.  Remove global_var,
+       call_clobbered_vars, call_used_vars, addressable_vars,
+       aliases_compted_p and mem_ref_stats members.  Add syms_to_rename,
+       escaped and callused members.
+       (struct ptr_info_def): Remove all members, add points-to solution
+       member pt.
+       (struct var_ann_d): Remove in_vuse_list, in_vdef_list,
+       call_clobbered, escape_mask, mpt and symbol_mem_tag members.
+       * Makefile.in (TREE_FLOW_H): Add tree-ssa-alias.h.
+       (tree-ssa-structalias.o): Remove tree-ssa-structalias.h.
+       (tree-ssa-alias.o): Likewise.
+       (toplev.o): Add tree-ssa-alias.h
+       (GTFILES): Remove tree-ssa-structalias.h, add tree-ssa-alias.h.
+       * gimple.c (gimple_set_bb): Fix off-by-one error.
+       (is_gimple_reg): Do not handle memory tags.
+       (gimple_copy): Also copy virtual operands.
+       Delay updating the statement.  Do not reset loaded and stored syms.
+       (gimple_set_stored_syms): Remove.
+       (gimple_set_loaded_syms): Likewise.
+       (gimple_call_copy_skip_args): Copy the virtual operands
+       and mark the new statement modified.
+       * tree-ssa-structalias.c (may_alias_p): Remove.
+       (set_uids_in_ptset): Take the alias set to prune with as
+       parameter.  Fold in the alias test of may_alias_p.
+       (compute_points_to_sets): Compute whether a ptr is dereferenced
+       in a local sbitmap.
+       (process_constraint): Deal with &ANYTHING on the lhs, reject all
+       other ADDRESSOF constraints on the lhs.
+       (get_constraint_for_component_ref): Assert that we don't get
+       ADDRESSOF constraints from the base of the reference.
+       Properly generate UNKNOWN_OFFSET for DEREF if needed.
+       (struct variable_info): Remove collapsed_to member.
+       (get_varinfo_fc): Remove.
+       (new_var_info): Do not set collapsed_to.
+       (dump_constraint): Do not follow cycles.
+       (dump_constraint_graph): Likewise.
+       (build_pred_graph): Likewise.
+       (build_succ_graph): Likewise.
+       (rewrite_constraints): Likewise.
+       (do_simple_structure_copy): Remove.
+       (do_rhs_deref_structure_copy): Remove.
+       (do_lhs_deref_structure_copy): Remove.
+       (collapse_rest_of_var): Remove.
+       (do_structure_copy): Re-implement.
+       (pta_stats): New global variable.
+       (dump_pta_stats): New function.
+       (struct constraint_expr): Make offset signed.
+       (UNKNOWN_OFFSET): Define special value.
+       (dump_constraint): Dump UNKNOWN_OFFSET as UNKNOWN.
+       (solution_set_expand): New helper function split out from ...
+       (do_sd_constraint): ... here.
+       (solution_set_add): Handle UNKNOWN_OFFSET.  Handle negative offsets.
+       (do_ds_constraint): Likewise.
+       (do_sd_constraint): Likewise.  Do not special-case ESCAPED = *ESCAPED
+       and CALLUSED = *CALLUSED.
+       (set_union_with_increment): Make inc argument signed.
+       (type_safe): Remove.
+       (get_constraint_for_ptr_offset): Handle unknown and negative
+       constant offsets.
+       (first_vi_for_offset): Handle offsets before start.  Bail
+       out early for offsets beyond the variable extent.
+       (first_or_preceding_vi_for_offset): New function.
+       (init_base_vars): Add ESCAPED = ESCAPED + UNKNOWN_OFFSET constraint.
+       Together with ESCAPED = *ESCAPED this properly computes reachability.
+       (find_what_var_points_to): New function.
+       (find_what_p_points_to): Implement in terms of find_what_var_points_to.
+       (pt_solution_reset, pt_solution_empty_p, pt_solution_includes_global,
+       pt_solution_includes_1, pt_solution_includes, pt_solutions_intersect_1,
+       pt_solutions_intersect): New functions.
+       (compute_call_used_vars): Remove.
+       (compute_may_aliases): New main entry into PTA computation.
+       * gimple.h (gimple_p): New typedef.
+       (struct gimple_statement_base): Remove references_memory_p.
+       (struct gimple_statement_with_memory_ops_base): Remove
+       vdef_ops, vuse_ops, stores and loads members.  Add vdef and vuse
+       members.
+       (gimple_vuse_ops, gimple_set_vuse_ops, gimple_vdef_ops,
+       gimple_set_vdef_ops, gimple_loaded_syms, gimple_stored_syms,
+       gimple_set_references_memory): Remove.
+       (gimple_vuse_op, gimple_vdef_op, gimple_vuse, gimple_vdef,
+       gimple_vuse_ptr, gimple_vdef_ptri, gimple_set_vuse, gimple_set_vdef):
+       New functions.
+       * tree-cfg.c (move_block_to_fn): Fix off-by-one error.
+       (verify_expr): Allow RESULT_DECL.
+       (gimple_duplicate_bb): Do not copy virtual operands.
+       (gimple_duplicate_sese_region): Adjust.
+       (gimple_duplicate_sese_tail): Likewise.
+       (mark_virtual_ops_in_region): Remove.
+       (move_sese_region_to_fn): Do not call it.
+       * passes.c (init_optimization_passes): Remove pass_reset_cc_flags
+       and pass_simple_dse.
+       (execute_function_todo): Handle TODO_update_address_taken,
+       call execute_update_addresses_taken for TODO_rebuild_alias.
+       (execute_todo): Adjust.
+       (execute_one_pass): Init dump files early.
+       * ipa-struct-reorg.c (finalize_var_creation): Do not mark vars
+       call-clobbered.
+       (create_general_new_stmt): Clear vops.
+       * tree-ssa-reassoc.c (get_rank): Adjust.
+       * tree-vect-slp.c (vect_create_mask_and_perm): Do not mark
+       symbols for renaming.
+       * params.def (PARAM_MAX_ALIASED_VOPS): Remove.
+       (PARAM_AVG_ALIASED_VOPS): Likewise.
+       * tree-ssanames.c (init_ssanames): Allocate SYMS_TO_RENAME.
+       (duplicate_ssa_name_ptr_info): No need to copy the shared bitmaps.
+       * tree-ssa-operands.c: Simplify for new virtual operand
+       representation.
+       (operand_build_cmp, copy_virtual_operands,
+       create_ssa_artificial_load_stmt, add_to_addressable_set,
+       gimple_add_to_addresses_taken): Remove public functions.
+       (unlink_stmt_vdef): New function.
+
 2009-04-03  Alan Modra  <amodra@bigpond.net.au>
 
        * config.gcc (powerpc-*-linux*): Merge variants.
index 79780e9..31c5898 100644 (file)
@@ -856,7 +856,8 @@ CPP_INTERNAL_H = $(srcdir)/../libcpp/internal.h $(CPP_ID_DATA_H)
 TREE_DUMP_H = tree-dump.h $(SPLAY_TREE_H) tree-pass.h
 TREE_FLOW_H = tree-flow.h tree-flow-inline.h tree-ssa-operands.h \
                $(BITMAP_H) $(BASIC_BLOCK_H) hard-reg-set.h $(GIMPLE_H) \
-               $(HASHTAB_H) $(CGRAPH_H) $(IPA_REFERENCE_H)
+               $(HASHTAB_H) $(CGRAPH_H) $(IPA_REFERENCE_H) \
+               tree-ssa-alias.h
 TREE_SSA_LIVE_H = tree-ssa-live.h $(PARTITION_H) vecprim.h
 PRETTY_PRINT_H = pretty-print.h $(INPUT_H) $(OBSTACK_H)
 DIAGNOSTIC_H = diagnostic.h diagnostic.def $(PRETTY_PRINT_H) options.h
@@ -2069,7 +2070,7 @@ stor-layout.o : stor-layout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
    $(TREE_H) $(PARAMS_H) $(FLAGS_H) $(FUNCTION_H) $(EXPR_H) output.h $(RTL_H) \
    $(GGC_H) $(TM_P_H) $(TARGET_H) langhooks.h $(REGS_H) gt-stor-layout.h \
    $(TOPLEV_H)
-tree-ssa-structalias.o: tree-ssa-structalias.c tree-ssa-structalias.h \
+tree-ssa-structalias.o: tree-ssa-structalias.c \
    $(SYSTEM_H) $(CONFIG_H) coretypes.h $(TM_H) $(GGC_H) $(OBSTACK_H) $(BITMAP_H) \
    $(FLAGS_H) $(RTL_H) $(TM_P_H) hard-reg-set.h $(BASIC_BLOCK_H) output.h \
    $(DIAGNOSTIC_H) $(TREE_H) $(C_COMMON_H) $(TREE_FLOW_H) $(TREE_INLINE_H) varray.h \
@@ -2291,7 +2292,7 @@ tree-ssa-alias.o : tree-ssa-alias.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
    $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) $(TREE_INLINE_H) $(FLAGS_H) \
    $(FUNCTION_H) $(TIMEVAR_H) convert.h $(TM_H) coretypes.h langhooks.h \
    $(TREE_DUMP_H) tree-pass.h $(PARAMS_H) $(BASIC_BLOCK_H) $(DIAGNOSTIC_H) \
-   hard-reg-set.h $(GIMPLE_H) vec.h tree-ssa-structalias.h \
+   hard-reg-set.h $(GIMPLE_H) vec.h \
    $(IPA_TYPE_ESCAPE_H) vecprim.h pointer-set.h alloc-pool.h
 tree-ssa-reassoc.o : tree-ssa-reassoc.c $(TREE_FLOW_H) $(CONFIG_H) \
    $(SYSTEM_H) $(TREE_H) $(GGC_H) $(DIAGNOSTIC_H) $(TIMEVAR_H) \
@@ -2442,7 +2443,8 @@ toplev.o : toplev.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
    value-prof.h $(PARAMS_H) $(TM_P_H) reload.h ira.h dwarf2asm.h $(TARGET_H) \
    langhooks.h insn-flags.h $(CFGLAYOUT_H) $(CFGLOOP_H) hosthooks.h \
    $(CGRAPH_H) $(COVERAGE_H) alloc-pool.h $(GGC_H) $(INTEGRATE_H) \
-   opts.h params.def tree-mudflap.h $(REAL_H) tree-pass.h $(GIMPLE_H)
+   opts.h params.def tree-mudflap.h $(REAL_H) tree-pass.h $(GIMPLE_H) \
+   tree-ssa-alias.h
        $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) \
          -DTARGET_NAME=\"$(target_noncanonical)\" \
          -c $(srcdir)/toplev.c $(OUTPUT_OPTION)
@@ -3304,8 +3306,9 @@ GTFILES = $(CPP_ID_DATA_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
   $(srcdir)/targhooks.c $(out_file) $(srcdir)/passes.c $(srcdir)/cgraphunit.c \
   $(srcdir)/tree-ssa-propagate.c \
   $(srcdir)/tree-phinodes.c \
-  $(srcdir)/ipa-reference.c $(srcdir)/tree-ssa-structalias.h \
+  $(srcdir)/ipa-reference.c \
   $(srcdir)/tree-ssa-structalias.c $(srcdir)/tree-inline.c \
+  $(srcdir)/tree-ssa-alias.h \
   @all_gtfiles@
 
 # Compute the list of GT header files from the corresponding C sources,
index 2ebde8d..2bc8702 100644 (file)
@@ -518,6 +518,98 @@ component_uses_parent_alias_set (const_tree t)
     }
 }
 
+/* Return the alias set for the memory pointed to by T, which may be
+   either a type or an expression.  Return -1 if there is nothing
+   special about dereferencing T.  */
+
+static alias_set_type
+get_deref_alias_set_1 (tree t)
+{
+  /* If we're not doing any alias analysis, just assume everything
+     aliases everything else.  */
+  if (!flag_strict_aliasing)
+    return 0;
+
+  if (! TYPE_P (t))
+    {
+      tree decl = find_base_decl (t);
+
+      if (decl && DECL_POINTER_ALIAS_SET_KNOWN_P (decl))
+       {
+         /* If we haven't computed the actual alias set, do it now.  */
+         if (DECL_POINTER_ALIAS_SET (decl) == -2)
+           {
+             tree pointed_to_type = TREE_TYPE (TREE_TYPE (decl));
+
+             /* No two restricted pointers can point at the same thing.
+                However, a restricted pointer can point at the same thing
+                as an unrestricted pointer, if that unrestricted pointer
+                is based on the restricted pointer.  So, we make the
+                alias set for the restricted pointer a subset of the
+                alias set for the type pointed to by the type of the
+                decl.  */
+             alias_set_type pointed_to_alias_set
+                 = get_alias_set (pointed_to_type);
+
+             if (pointed_to_alias_set == 0)
+               /* It's not legal to make a subset of alias set zero.  */
+               DECL_POINTER_ALIAS_SET (decl) = 0;
+             else if (AGGREGATE_TYPE_P (pointed_to_type))
+               /* For an aggregate, we must treat the restricted
+                  pointer the same as an ordinary pointer.  If we
+                  were to make the type pointed to by the
+                  restricted pointer a subset of the pointed-to
+                  type, then we would believe that other subsets
+                  of the pointed-to type (such as fields of that
+                  type) do not conflict with the type pointed to
+                  by the restricted pointer.  */
+               DECL_POINTER_ALIAS_SET (decl)
+                   = pointed_to_alias_set;
+             else
+               {
+                 DECL_POINTER_ALIAS_SET (decl) = new_alias_set ();
+                 record_alias_subset (pointed_to_alias_set,
+                                      DECL_POINTER_ALIAS_SET (decl));
+               }
+           }
+
+         /* We use the alias set indicated in the declaration.  */
+         return DECL_POINTER_ALIAS_SET (decl);
+       }
+
+      /* Now all we care about is the type.  */
+      t = TREE_TYPE (t);
+    }
+
+  /* If we have an INDIRECT_REF via a void pointer, we don't
+     know anything about what that might alias.  Likewise if the
+     pointer is marked that way.  */
+  if (TREE_CODE (TREE_TYPE (t)) == VOID_TYPE
+      || TYPE_REF_CAN_ALIAS_ALL (t))
+    return 0;
+
+  return -1;
+}
+
+/* Return the alias set for the memory pointed to by T, which may be
+   either a type or an expression.  */
+
+alias_set_type
+get_deref_alias_set (tree t)
+{
+  alias_set_type set = get_deref_alias_set_1 (t);
+
+  /* Fall back to the alias-set of the pointed-to type.  */
+  if (set == -1)
+    {
+      if (! TYPE_P (t))
+       t = TREE_TYPE (t);
+      set = get_alias_set (TREE_TYPE (t));
+    }
+
+  return set;
+}
+
 /* Return the alias set for T, which may be either a type or an
    expression.  Call language-specific routine for help, if needed.  */
 
@@ -558,66 +650,11 @@ get_alias_set (tree t)
          STRIP_NOPS (inner);
        }
 
-      /* Check for accesses through restrict-qualified pointers.  */
       if (INDIRECT_REF_P (inner))
        {
-         tree decl;
-
-         if (TREE_CODE (TREE_OPERAND (inner, 0)) == SSA_NAME)
-           decl = SSA_NAME_VAR (TREE_OPERAND (inner, 0));
-         else
-           decl = find_base_decl (TREE_OPERAND (inner, 0));
-
-         if (decl && DECL_POINTER_ALIAS_SET_KNOWN_P (decl))
-           {
-             /* If we haven't computed the actual alias set, do it now.  */
-             if (DECL_POINTER_ALIAS_SET (decl) == -2)
-               {
-                 tree pointed_to_type = TREE_TYPE (TREE_TYPE (decl));
-
-                 /* No two restricted pointers can point at the same thing.
-                    However, a restricted pointer can point at the same thing
-                    as an unrestricted pointer, if that unrestricted pointer
-                    is based on the restricted pointer.  So, we make the
-                    alias set for the restricted pointer a subset of the
-                    alias set for the type pointed to by the type of the
-                    decl.  */
-                 alias_set_type pointed_to_alias_set
-                   = get_alias_set (pointed_to_type);
-
-                 if (pointed_to_alias_set == 0)
-                   /* It's not legal to make a subset of alias set zero.  */
-                   DECL_POINTER_ALIAS_SET (decl) = 0;
-                 else if (AGGREGATE_TYPE_P (pointed_to_type))
-                   /* For an aggregate, we must treat the restricted
-                      pointer the same as an ordinary pointer.  If we
-                      were to make the type pointed to by the
-                      restricted pointer a subset of the pointed-to
-                      type, then we would believe that other subsets
-                      of the pointed-to type (such as fields of that
-                      type) do not conflict with the type pointed to
-                      by the restricted pointer.  */
-                   DECL_POINTER_ALIAS_SET (decl)
-                     = pointed_to_alias_set;
-                 else
-                   {
-                     DECL_POINTER_ALIAS_SET (decl) = new_alias_set ();
-                     record_alias_subset (pointed_to_alias_set,
-                                          DECL_POINTER_ALIAS_SET (decl));
-                   }
-               }
-
-             /* We use the alias set indicated in the declaration.  */
-             return DECL_POINTER_ALIAS_SET (decl);
-           }
-
-         /* If we have an INDIRECT_REF via a void pointer, we don't
-            know anything about what that might alias.  Likewise if the
-            pointer is marked that way.  */
-         else if (TREE_CODE (TREE_TYPE (inner)) == VOID_TYPE
-                  || (TYPE_REF_CAN_ALIAS_ALL
-                      (TREE_TYPE (TREE_OPERAND (inner, 0)))))
-           return 0;
+         set = get_deref_alias_set_1 (TREE_OPERAND (inner, 0));
+         if (set != -1)
+           return set;
        }
 
       /* Otherwise, pick up the outermost object that we could have a pointer
index c760392..5907215 100644 (file)
@@ -32,6 +32,7 @@ typedef int alias_set_type;
 
 extern alias_set_type new_alias_set (void);
 extern alias_set_type get_alias_set (tree);
+extern alias_set_type get_deref_alias_set (tree);
 extern alias_set_type get_varargs_alias_set (void);
 extern alias_set_type get_frame_alias_set (void);
 extern bool component_uses_parent_alias_set (const_tree);
index 6680389..5eb9776 100644 (file)
@@ -7584,32 +7584,6 @@ Maximum number of basic blocks on path that cse considers.  The default is 10.
 @item max-cse-insns
 The maximum instructions CSE process before flushing. The default is 1000.
 
-@item max-aliased-vops
-
-Maximum number of virtual operands per function allowed to represent
-aliases before triggering the alias partitioning heuristic.  Alias
-partitioning reduces compile times and memory consumption needed for
-aliasing at the expense of precision loss in alias information.  The
-default value for this parameter is 100 for -O1, 500 for -O2 and 1000
-for -O3.
-
-Notice that if a function contains more memory statements than the
-value of this parameter, it is not really possible to achieve this
-reduction.  In this case, the compiler will use the number of memory
-statements as the value for @option{max-aliased-vops}.
-
-@item avg-aliased-vops
-
-Average number of virtual operands per statement allowed to represent
-aliases before triggering the alias partitioning heuristic.  This
-works in conjunction with @option{max-aliased-vops}.  If a function
-contains more than @option{max-aliased-vops} virtual operators, then
-memory symbols will be grouped into memory partitions until either the
-total number of virtual operators is below @option{max-aliased-vops}
-or the average number of virtual operators per memory statement is
-below @option{avg-aliased-vops}.  The default value for this parameter
-is 1 for -O1 and -O2, and 3 for -O3.
-
 @item ggc-min-expand
 
 GCC uses a garbage collector to manage its own memory allocation.  This
index bd0edc4..659431b 100644 (file)
@@ -795,230 +795,100 @@ is popped.
 @cindex flow-sensitive alias analysis
 @cindex flow-insensitive alias analysis
 
-Alias analysis proceeds in 4 main phases:
+Alias analysis in GIMPLE SSA form consists of two pieces.  First
+the virtual SSA web ties conflicting memory accesses and provides
+a SSA use-def chain and SSA immediate-use chains for walking
+possibly dependent memory accesses.  Second an alias-oracle can
+be queried to disambiguate explicit and implicit memory references.
 
 @enumerate
-@item   Structural alias analysis.
+@item Memory SSA form.
 
-This phase walks the types for structure variables, and determines which
-of the fields can overlap using offset and size of each field.  For each
-field, a ``subvariable'' called a ``Structure field tag'' (SFT)@ is
-created, which represents that field as a separate variable.  All
-accesses that could possibly overlap with a given field will have
-virtual operands for the SFT of that field.
+All statements that may use memory have exactly one accompanied use of
+a virtual SSA name that represents the state of memory at the
+given point in the IL.
+
+All statements that may define memory have exactly one accompanied
+definition of a virtual SSA name using the previous state of memory
+and defining the new state of memory after the given point in the IL.
 
 @smallexample
-struct foo
-@{
-  int a;
-  int b;
-@}
-struct foo temp;
-int bar (void)
+int i;
+int foo (void)
 @{
-  int tmp1, tmp2, tmp3;
-  SFT.0_2 = VDEF <SFT.0_1>
-  temp.a = 5;
-  SFT.1_4 = VDEF <SFT.1_3>
-  temp.b = 6;
-  
-  VUSE <SFT.1_4>
-  tmp1_5 = temp.b;
-  VUSE <SFT.0_2>
-  tmp2_6 = temp.a;
-
-  tmp3_7 = tmp1_5 + tmp2_6;
-  return tmp3_7;
+  # .MEM_3 = VDEF <.MEM_2(D)>
+  i = 1;
+  # VUSE <.MEM_3>
+  return i;
 @}
 @end smallexample
 
-If you copy the symbol tag for a variable for some reason, you probably
-also want to copy the subvariables for that variable.
+The virtual SSA names in this case are @code{.MEM_2(D)} and
+@code{.MEM_3}.  The store to the global variable @code{i}
+defines @code{.MEM_3} invalidating @code{.MEM_2(D)}.  The
+load from @code{i} uses that new state @code{.MEM_3}.
+
+The virtual SSA web serves as constraints to SSA optimizers
+preventing illegitimate code-motion and optimization.  It
+also provides a way to walk related memory statements.
 
 @item Points-to and escape analysis.
 
-This phase walks the use-def chains in the SSA web looking for
-three things:
+Points-to analysis builds a set of constraints from the GIMPLE
+SSA IL representing all pointer operations and facts we do
+or do not know about pointers.  Solving this set of constraints
+yields a conservatively correct solution for each pointer
+variable in the program (though we are only interested in
+SSA name pointers) as to what it may possibly point to.
+
+This points-to solution for a given SSA name pointer is stored
+in the @code{pt_solution} sub-structure of the
+@code{SSA_NAME_PTR_INFO} record.  The following accessor
+functions are available:
 
 @itemize @bullet
-@item Assignments of the form @code{P_i = &VAR}
-@item Assignments of the form P_i = malloc()
-@item Pointers and ADDR_EXPR that escape the current function.
+@item @code{pt_solution_includes}
+@item @code{pt_solutions_intersect}
 @end itemize
 
-The concept of `escaping' is the same one used in the Java world.
-When a pointer or an ADDR_EXPR escapes, it means that it has been
-exposed outside of the current function.  So, assignment to
-global variables, function arguments and returning a pointer are
-all escape sites.
-
-This is where we are currently limited.  Since not everything is
-renamed into SSA, we lose track of escape properties when a
-pointer is stashed inside a field in a structure, for instance.
-In those cases, we are assuming that the pointer does escape.
-
-We use escape analysis to determine whether a variable is
-call-clobbered.  Simply put, if an ADDR_EXPR escapes, then the
-variable is call-clobbered.  If a pointer P_i escapes, then all
-the variables pointed-to by P_i (and its memory tag) also escape.
-
-@item Compute flow-sensitive aliases
+Points-to analysis also computes the solution for two special
+set of pointers, @code{ESCAPED} and @code{CALLUSED}.  Those
+represent all memory that has escaped the scope of analysis
+or that is used by pure or nested const calls.
 
-We have two classes of memory tags.  Memory tags associated with
-the pointed-to data type of the pointers in the program.  These
-tags are called ``symbol memory tag'' (SMT)@.  The other class are
-those associated with SSA_NAMEs, called ``name memory tag'' (NMT)@.
-The basic idea is that when adding operands for an INDIRECT_REF
-*P_i, we will first check whether P_i has a name tag, if it does
-we use it, because that will have more precise aliasing
-information.  Otherwise, we use the standard symbol tag.
+@item Type-based alias analysis
 
-In this phase, we go through all the pointers we found in
-points-to analysis and create alias sets for the name memory tags
-associated with each pointer P_i.  If P_i escapes, we mark
-call-clobbered the variables it points to and its tag.
-
-
-@item Compute flow-insensitive aliases
-
-This pass will compare the alias set of every symbol memory tag and
-every addressable variable found in the program.  Given a symbol
-memory tag SMT and an addressable variable V@.  If the alias sets
-of SMT and V conflict (as computed by may_alias_p), then V is
-marked as an alias tag and added to the alias set of SMT@.
+Type-based alias analysis is frontend dependent though generic
+support is provided by the middle-end in @code{alias.c}.  TBAA
+code is used by both tree optimizers and RTL optimizers.
 
 Every language that wishes to perform language-specific alias analysis
 should define a function that computes, given a @code{tree}
 node, an alias set for the node.  Nodes in different alias sets are not
 allowed to alias.  For an example, see the C front-end function
 @code{c_get_alias_set}.
-@end enumerate
-
-For instance, consider the following function:
-
-@smallexample
-foo (int i)
-@{
-  int *p, *q, a, b;
-
-  if (i > 10)
-    p = &a;
-  else
-    q = &b;
-
-  *p = 3;
-  *q = 5;
-  a = b + 2;
-  return *p;
-@}
-@end smallexample
-
-After aliasing analysis has finished, the symbol memory tag for
-pointer @code{p} will have two aliases, namely variables @code{a} and
-@code{b}.
-Every time pointer @code{p} is dereferenced, we want to mark the
-operation as a potential reference to @code{a} and @code{b}.
-
-@smallexample
-foo (int i)
-@{
-  int *p, a, b;
-
-  if (i_2 > 10)
-    p_4 = &a;
-  else
-    p_6 = &b;
-  # p_1 = PHI <p_4(1), p_6(2)>;
 
-  # a_7 = VDEF <a_3>;
-  # b_8 = VDEF <b_5>;
-  *p_1 = 3;
+@item Tree alias-oracle
 
-  # a_9 = VDEF <a_7>
-  # VUSE <b_8>
-  a_9 = b_8 + 2;
+The tree alias-oracle provides means to disambiguate two memory
+references and memory references against statements.  The following
+queries are available:
 
-  # VUSE <a_9>;
-  # VUSE <b_8>;
-  return *p_1;
-@}
-@end smallexample
-
-In certain cases, the list of may aliases for a pointer may grow
-too large.  This may cause an explosion in the number of virtual
-operands inserted in the code.  Resulting in increased memory
-consumption and compilation time.
-
-When the number of virtual operands needed to represent aliased
-loads and stores grows too large (configurable with @option{--param
-max-aliased-vops}), alias sets are grouped to avoid severe
-compile-time slow downs and memory consumption.  The alias
-grouping heuristic proceeds as follows:
-
-@enumerate
-@item Sort the list of pointers in decreasing number of contributed
-virtual operands.
-
-@item Take the first pointer from the list and reverse the role
-of the memory tag and its aliases.  Usually, whenever an
-aliased variable Vi is found to alias with a memory tag
-T, we add Vi to the may-aliases set for T@.  Meaning that
-after alias analysis, we will have:
-
-@smallexample
-may-aliases(T) = @{ V1, V2, V3, @dots{}, Vn @}
-@end smallexample
-
-This means that every statement that references T, will get
-@code{n} virtual operands for each of the Vi tags.  But, when
-alias grouping is enabled, we make T an alias tag and add it
-to the alias set of all the Vi variables:
-
-@smallexample
-may-aliases(V1) = @{ T @}
-may-aliases(V2) = @{ T @}
-@dots{}
-may-aliases(Vn) = @{ T @}
-@end smallexample
-
-This has two effects: (a) statements referencing T will only get
-a single virtual operand, and, (b) all the variables Vi will now
-appear to alias each other.  So, we lose alias precision to
-improve compile time.  But, in theory, a program with such a high
-level of aliasing should not be very optimizable in the first
-place.
-
-@item Since variables may be in the alias set of more than one
-memory tag, the grouping done in step (2) needs to be extended
-to all the memory tags that have a non-empty intersection with
-the may-aliases set of tag T@.  For instance, if we originally
-had these may-aliases sets:
-
-@smallexample
-may-aliases(T) = @{ V1, V2, V3 @}
-may-aliases(R) = @{ V2, V4 @}
-@end smallexample
-
-In step (2) we would have reverted the aliases for T as:
-
-@smallexample
-may-aliases(V1) = @{ T @}
-may-aliases(V2) = @{ T @}
-may-aliases(V3) = @{ T @}
-@end smallexample
+@itemize @bullet
+@item @code{refs_may_alias_p}
+@item @code{ref_maybe_used_by_stmt_p}
+@item @code{stmt_may_clobber_ref_p}
+@end itemize
 
-But note that now V2 is no longer aliased with R@.  We could
-add R to may-aliases(V2), but we are in the process of
-grouping aliases to reduce virtual operands so what we do is
-add V4 to the grouping to obtain:
+In addition to those two kind of statement walkers are available
+walking statements related to a reference ref.
+@code{walk_non_aliased_vuses} walks over dominating memory defining
+statements and calls back if the statement does not clobber ref
+providing the non-aliased VUSE.  The walk stops at
+the first clobbering statement or if asked to.
+@code{walk_aliased_vdefs} walks over dominating memory defining
+statements and calls back on each statement clobbering ref
+providing its aliasing VDEF.  The walk stops if asked to.
 
-@smallexample
-may-aliases(V1) = @{ T @}
-may-aliases(V2) = @{ T @}
-may-aliases(V3) = @{ T @}
-may-aliases(V4) = @{ T @}
-@end smallexample
-
-@item If the total number of virtual operands due to aliasing is
-still above the threshold set by max-alias-vops, go back to (2).
 @end enumerate
+
index 733a449..163acf9 100644 (file)
@@ -1132,33 +1132,6 @@ dump_gimple_asm (pretty_printer *buffer, gimple gs, int spc, int flags)
 }
 
 
-/* Dump the set of decls SYMS.  BUFFER, SPC and FLAGS are as in
-   dump_generic_node.  */
-
-static void
-dump_symbols (pretty_printer *buffer, bitmap syms, int flags)
-{
-  unsigned i;
-  bitmap_iterator bi;
-
-  if (syms == NULL)
-    pp_string (buffer, "NIL");
-  else
-    {
-      pp_string (buffer, " { ");
-
-      EXECUTE_IF_SET_IN_BITMAP (syms, 0, i, bi)
-       {
-         tree sym = referenced_var_lookup (i);
-         dump_generic_node (buffer, sym, 0, flags, false);
-         pp_character (buffer, ' ');
-       }
-
-      pp_character (buffer, '}');
-    }
-}
-
-
 /* Dump a PHI node PHI.  BUFFER, SPC and FLAGS are as in
    dump_gimple_stmt.  */
 
@@ -1379,81 +1352,27 @@ dump_gimple_cdt (pretty_printer *buffer, gimple gs, int spc, int flags)
 static void
 dump_gimple_mem_ops (pretty_printer *buffer, gimple gs, int spc, int flags)
 {
-  struct voptype_d *vdefs;
-  struct voptype_d *vuses;
-  int i, n;
+  tree vdef = gimple_vdef (gs);
+  tree vuse = gimple_vuse (gs);
 
   if (!ssa_operands_active () || !gimple_references_memory_p (gs))
     return;
 
-  /* Even if the statement doesn't have virtual operators yet, it may
-     contain symbol information (this happens before aliases have been
-     computed).  */
-  if ((flags & TDF_MEMSYMS)
-      && gimple_vuse_ops (gs) == NULL
-      && gimple_vdef_ops (gs) == NULL)
-    {
-      if (gimple_loaded_syms (gs))
-       {
-         pp_string (buffer, "# LOADS: ");
-         dump_symbols (buffer, gimple_loaded_syms (gs), flags);
-         newline_and_indent (buffer, spc);
-       }
-
-      if (gimple_stored_syms (gs))
-       {
-         pp_string (buffer, "# STORES: ");
-         dump_symbols (buffer, gimple_stored_syms (gs), flags);
-         newline_and_indent (buffer, spc);
-       }
-
-      return;
-    }
-
-  vuses = gimple_vuse_ops (gs);
-  while (vuses)
+  if (vdef != NULL_TREE)
     {
-      pp_string (buffer, "# VUSE <");
-
-      n = VUSE_NUM (vuses);
-      for (i = 0; i < n; i++)
-       {
-         dump_generic_node (buffer, VUSE_OP (vuses, i), spc + 2, flags, false);
-         if (i < n - 1)
-           pp_string (buffer, ", ");
-       }
-
+      pp_string (buffer, "# ");
+      dump_generic_node (buffer, vdef, spc + 2, flags, false);
+      pp_string (buffer, " = VDEF <");
+      dump_generic_node (buffer, vuse, spc + 2, flags, false);
       pp_character (buffer, '>');
-
-      if (flags & TDF_MEMSYMS)
-       dump_symbols (buffer, gimple_loaded_syms (gs), flags);
-
       newline_and_indent (buffer, spc);
-      vuses = vuses->next;
     }
-
-  vdefs = gimple_vdef_ops (gs);
-  while (vdefs)
+  else if (vuse != NULL_TREE)
     {
-      pp_string (buffer, "# ");
-      dump_generic_node (buffer, VDEF_RESULT (vdefs), spc + 2, flags, false);
-      pp_string (buffer, " = VDEF <");
-
-      n = VDEF_NUM (vdefs);
-      for (i = 0; i < n; i++)
-       {
-         dump_generic_node (buffer, VDEF_OP (vdefs, i), spc + 2, flags, 0);
-         if (i < n - 1)
-           pp_string (buffer, ", ");
-       }
-
+      pp_string (buffer, "# VUSE <");
+      dump_generic_node (buffer, vuse, spc + 2, flags, false);
       pp_character (buffer, '>');
-
-      if ((flags & TDF_MEMSYMS) && vdefs->next == NULL)
-       dump_symbols (buffer, gimple_stored_syms (gs), flags);
-
       newline_and_indent (buffer, spc);
-      vdefs = vdefs->next;
     }
 }
 
index a1dd6a7..4d05c98 100644 (file)
@@ -1902,7 +1902,7 @@ gimple_set_bb (gimple stmt, basic_block bb)
          LABEL_DECL_UID (t) = uid = cfun->cfg->last_label_uid++;
          if (old_len <= (unsigned) uid)
            {
-             unsigned new_len = 3 * uid / 2;
+             unsigned new_len = 3 * uid / 2 + 1;
 
              VEC_safe_grow_cleared (basic_block, gc, label_to_block_map,
                                     new_len);
@@ -2209,13 +2209,12 @@ gimple_copy (gimple stmt)
 
       if (gimple_has_mem_ops (stmt))
        {
-         gimple_set_vdef_ops (copy, NULL);
-         gimple_set_vuse_ops (copy, NULL);
-         copy->gsmem.membase.stores = NULL;
-         copy->gsmem.membase.loads = NULL;
+         gimple_set_vdef (copy, gimple_vdef (stmt));
+         gimple_set_vuse (copy, gimple_vuse (stmt));
        }
 
-      update_stmt (copy);
+      /* SSA operands need to be updated.  */
+      gimple_set_modified (copy, true);
     }
 
   return copy;
@@ -2456,46 +2455,6 @@ dump_gimple_statistics (void)
 }
 
 
-/* Deep copy SYMS into the set of symbols stored by STMT.  If SYMS is
-   NULL or empty, the storage used is freed up.  */
-
-void
-gimple_set_stored_syms (gimple stmt, bitmap syms, bitmap_obstack *obs)
-{
-  gcc_assert (gimple_has_mem_ops (stmt));
-
-  if (syms == NULL || bitmap_empty_p (syms))
-    BITMAP_FREE (stmt->gsmem.membase.stores);
-  else
-    {
-      if (stmt->gsmem.membase.stores == NULL)
-       stmt->gsmem.membase.stores = BITMAP_ALLOC (obs);
-
-      bitmap_copy (stmt->gsmem.membase.stores, syms);
-    }
-}
-
-
-/* Deep copy SYMS into the set of symbols loaded by STMT.  If SYMS is
-   NULL or empty, the storage used is freed up.  */
-
-void
-gimple_set_loaded_syms (gimple stmt, bitmap syms, bitmap_obstack *obs)
-{
-  gcc_assert (gimple_has_mem_ops (stmt));
-
-  if (syms == NULL || bitmap_empty_p (syms))
-    BITMAP_FREE (stmt->gsmem.membase.loads);
-  else
-    {
-      if (stmt->gsmem.membase.loads == NULL)
-       stmt->gsmem.membase.loads = BITMAP_ALLOC (obs);
-
-      bitmap_copy (stmt->gsmem.membase.loads, syms);
-    }
-}
-
-
 /* Return the number of operands needed on the RHS of a GIMPLE
    assignment for an expression with tree code CODE.  */
 
@@ -2866,9 +2825,6 @@ is_gimple_reg (tree t)
   if (TREE_CODE (t) == SSA_NAME)
     t = SSA_NAME_VAR (t);
 
-  if (MTAG_P (t))
-    return false;
-
   if (!is_gimple_variable (t))
     return false;
 
@@ -3127,6 +3083,9 @@ gimple_call_copy_skip_args (gimple stmt, bitmap args_to_skip)
   if (gimple_call_lhs (stmt))
     gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
 
+  gimple_set_vuse (new_stmt, gimple_vuse (stmt));
+  gimple_set_vdef (new_stmt, gimple_vdef (stmt));
+
   gimple_set_block (new_stmt, gimple_block (stmt));
   if (gimple_has_location (stmt))
     gimple_set_location (new_stmt, gimple_location (stmt));
@@ -3138,7 +3097,101 @@ gimple_call_copy_skip_args (gimple stmt, bitmap args_to_skip)
   gimple_call_set_return_slot_opt (new_stmt, gimple_call_return_slot_opt_p (stmt));
   gimple_call_set_from_thunk (new_stmt, gimple_call_from_thunk_p (stmt));
   gimple_call_set_va_arg_pack (new_stmt, gimple_call_va_arg_pack_p (stmt));
+
+  gimple_set_modified (new_stmt, true);
+
   return new_stmt;
 }
 
+
+/* Data structure used to count the number of dereferences to PTR
+   inside an expression.  */
+struct count_ptr_d
+{
+  tree ptr;
+  unsigned num_stores;
+  unsigned num_loads;
+};
+
+/* Helper for count_uses_and_derefs.  Called by walk_tree to look for
+   (ALIGN/MISALIGNED_)INDIRECT_REF nodes for the pointer passed in DATA.  */
+
+static tree
+count_ptr_derefs (tree *tp, int *walk_subtrees, void *data)
+{
+  struct walk_stmt_info *wi_p = (struct walk_stmt_info *) data;
+  struct count_ptr_d *count_p = (struct count_ptr_d *) wi_p->info;
+
+  /* Do not walk inside ADDR_EXPR nodes.  In the expression &ptr->fld,
+     pointer 'ptr' is *not* dereferenced, it is simply used to compute
+     the address of 'fld' as 'ptr + offsetof(fld)'.  */
+  if (TREE_CODE (*tp) == ADDR_EXPR)
+    {
+      *walk_subtrees = 0;
+      return NULL_TREE;
+    }
+
+  if (INDIRECT_REF_P (*tp) && TREE_OPERAND (*tp, 0) == count_p->ptr)
+    {
+      if (wi_p->is_lhs)
+       count_p->num_stores++;
+      else
+       count_p->num_loads++;
+    }
+
+  return NULL_TREE;
+}
+
+/* Count the number of direct and indirect uses for pointer PTR in
+   statement STMT.  The number of direct uses is stored in
+   *NUM_USES_P.  Indirect references are counted separately depending
+   on whether they are store or load operations.  The counts are
+   stored in *NUM_STORES_P and *NUM_LOADS_P.  */
+
+void
+count_uses_and_derefs (tree ptr, gimple stmt, unsigned *num_uses_p,
+                      unsigned *num_loads_p, unsigned *num_stores_p)
+{
+  ssa_op_iter i;
+  tree use;
+
+  *num_uses_p = 0;
+  *num_loads_p = 0;
+  *num_stores_p = 0;
+
+  /* Find out the total number of uses of PTR in STMT.  */
+  FOR_EACH_SSA_TREE_OPERAND (use, stmt, i, SSA_OP_USE)
+    if (use == ptr)
+      (*num_uses_p)++;
+
+  /* Now count the number of indirect references to PTR.  This is
+     truly awful, but we don't have much choice.  There are no parent
+     pointers inside INDIRECT_REFs, so an expression like
+     '*x_1 = foo (x_1, *x_1)' needs to be traversed piece by piece to
+     find all the indirect and direct uses of x_1 inside.  The only
+     shortcut we can take is the fact that GIMPLE only allows
+     INDIRECT_REFs inside the expressions below.  */
+  if (is_gimple_assign (stmt)
+      || gimple_code (stmt) == GIMPLE_RETURN
+      || gimple_code (stmt) == GIMPLE_ASM
+      || is_gimple_call (stmt))
+    {
+      struct walk_stmt_info wi;
+      struct count_ptr_d count;
+
+      count.ptr = ptr;
+      count.num_stores = 0;
+      count.num_loads = 0;
+
+      memset (&wi, 0, sizeof (wi));
+      wi.info = &count;
+      walk_gimple_op (stmt, count_ptr_derefs, &wi);
+
+      *num_stores_p = count.num_stores;
+      *num_loads_p = count.num_loads;
+    }
+
+  gcc_assert (*num_uses_p >= *num_loads_p + *num_stores_p);
+}
+
 #include "gt-gimple.h"
index b482c1d..dde7f94 100644 (file)
@@ -34,6 +34,10 @@ DEF_VEC_P(gimple);
 DEF_VEC_ALLOC_P(gimple,heap);
 DEF_VEC_ALLOC_P(gimple,gc);
 
+typedef gimple *gimple_p;
+DEF_VEC_P(gimple_p);
+DEF_VEC_ALLOC_P(gimple_p,heap);
+
 DEF_VEC_P(gimple_seq);
 DEF_VEC_ALLOC_P(gimple_seq,gc);
 DEF_VEC_ALLOC_P(gimple_seq,heap);
@@ -288,8 +292,8 @@ struct gimple_statement_base GTY(())
   /* Nonzero if this statement contains volatile operands.  */
   unsigned has_volatile_ops    : 1;
 
-  /* Nonzero if this statement contains memory refernces.  */
-  unsigned references_memory_p         : 1;
+  /* Padding to get subcode to 16 bit alignment.  */
+  unsigned pad                 : 1;
 
   /* The SUBCODE field can be used for tuple-specific flags for tuples
      that do not require subcodes.  Note that SUBCODE should be at
@@ -363,15 +367,11 @@ struct gimple_statement_with_memory_ops_base GTY(())
   /* [ WORD 1-7 ]  */
   struct gimple_statement_with_ops_base opbase;
 
-  /* [ WORD 8-9 ]  
-     Vectors for virtual operands.  */
-  struct voptype_d GTY((skip (""))) *vdef_ops;
-  struct voptype_d GTY((skip (""))) *vuse_ops;
-
-  /* [ WORD 9-10 ]
-     Symbols stored/loaded by this statement.  */
-  bitmap GTY((skip (""))) stores;
-  bitmap GTY((skip (""))) loads;
+  /* [ WORD 8-9 ]
+     Virtual operands for this statement.  The GC will pick them
+     up via the ssa_names array.  */
+  tree GTY((skip (""))) vdef;
+  tree GTY((skip (""))) vuse;
 };
 
 
@@ -379,10 +379,10 @@ struct gimple_statement_with_memory_ops_base GTY(())
 
 struct gimple_statement_with_memory_ops GTY(())
 {
-  /* [ WORD 1-10 ]  */
+  /* [ WORD 1-9 ]  */
   struct gimple_statement_with_memory_ops_base membase;
 
-  /* [ WORD 11 ]
+  /* [ WORD 10 ]
      Operand vector.  NOTE!  This must always be the last field
      of this structure.  In particular, this means that this
      structure cannot be embedded inside another one.  */
@@ -545,20 +545,20 @@ struct gimple_statement_wce GTY(())
 
 struct gimple_statement_asm GTY(())
 {
-  /* [ WORD 1-10 ]  */
+  /* [ WORD 1-9 ]  */
   struct gimple_statement_with_memory_ops_base membase;
 
-  /* [ WORD 11 ]
+  /* [ WORD 10 ]
      __asm__ statement.  */
   const char *string;
 
-  /* [ WORD 12 ]
+  /* [ WORD 11 ]
        Number of inputs, outputs and clobbers.  */
   unsigned char ni;
   unsigned char no;
   unsigned short nc;
 
-  /* [ WORD 13 ]
+  /* [ WORD 12 ]
      Operand vector.  NOTE!  This must always be the last field
      of this structure.  In particular, this means that this
      structure cannot be embedded inside another one.  */
@@ -907,6 +907,8 @@ extern bool is_gimple_call_addr (tree);
 extern tree get_call_expr_in (tree t);
 
 extern void recalculate_side_effects (tree);
+extern void count_uses_and_derefs (tree, gimple, unsigned *, unsigned *,
+                                  unsigned *);
 
 /* In gimplify.c  */
 extern tree create_tmp_var_raw (tree, const char *);
@@ -1010,9 +1012,6 @@ extern tree gimple_assign_rhs_to_tree (gimple);
 /* In builtins.c  */
 extern bool validate_gimple_arglist (const_gimple, ...);
 
-/* In tree-ssa-operands.c  */
-extern void gimple_add_to_addresses_taken (gimple, tree);
-
 /* In tree-ssa.c  */
 extern bool tree_ssa_useless_type_conversion (tree);
 extern bool useless_type_conversion_p (tree, tree);
@@ -1314,69 +1313,93 @@ gimple_set_use_ops (gimple g, struct use_optype_d *use)
 }
 
 
-/* Return the set of VUSE operands for statement G.  */
+/* Return the set of VUSE operand for statement G.  */
 
-static inline struct voptype_d *
-gimple_vuse_ops (const_gimple g)
+static inline use_operand_p
+gimple_vuse_op (const_gimple g)
 {
+  struct use_optype_d *ops;
   if (!gimple_has_mem_ops (g))
-    return NULL;
-  return g->gsmem.membase.vuse_ops;
+    return NULL_USE_OPERAND_P;
+  ops = g->gsops.opbase.use_ops;
+  if (ops
+      && USE_OP_PTR (ops)->use == &g->gsmem.membase.vuse)
+    return USE_OP_PTR (ops);
+  return NULL_USE_OPERAND_P;
 }
 
+/* Return the set of VDEF operand for statement G.  */
 
-/* Set OPS to be the set of VUSE operands for statement G.  */
-
-static inline void
-gimple_set_vuse_ops (gimple g, struct voptype_d *ops)
+static inline def_operand_p
+gimple_vdef_op (const_gimple g)
 {
-  gcc_assert (gimple_has_mem_ops (g));
-  g->gsmem.membase.vuse_ops = ops;
+  struct def_optype_d *ops;
+  if (!gimple_has_mem_ops (g))
+    return NULL_DEF_OPERAND_P;
+  ops = g->gsops.opbase.def_ops;
+  if (ops
+      && DEF_OP_PTR (ops) == &g->gsmem.membase.vdef)
+    return DEF_OP_PTR (ops);
+  return NULL_DEF_OPERAND_P;
 }
 
 
-/* Return the set of VDEF operands for statement G.  */
+/* Return the single VUSE operand of the statement G.  */
 
-static inline struct voptype_d *
-gimple_vdef_ops (const_gimple g)
+static inline tree
+gimple_vuse (const_gimple g)
 {
   if (!gimple_has_mem_ops (g))
-    return NULL;
-  return g->gsmem.membase.vdef_ops;
+    return NULL_TREE;
+  return g->gsmem.membase.vuse;
 }
 
+/* Return the single VDEF operand of the statement G.  */
 
-/* Set OPS to be the set of VDEF operands for statement G.  */
-
-static inline void
-gimple_set_vdef_ops (gimple g, struct voptype_d *ops)
+static inline tree
+gimple_vdef (const_gimple g)
 {
-  gcc_assert (gimple_has_mem_ops (g));
-  g->gsmem.membase.vdef_ops = ops;
+  if (!gimple_has_mem_ops (g))
+    return NULL_TREE;
+  return g->gsmem.membase.vdef;
 }
 
+/* Return the single VUSE operand of the statement G.  */
 
-/* Return the set of symbols loaded by statement G.  Each element of the
-   set is the DECL_UID of the corresponding symbol.  */
-
-static inline bitmap
-gimple_loaded_syms (const_gimple g)
+static inline tree *
+gimple_vuse_ptr (gimple g)
 {
   if (!gimple_has_mem_ops (g))
     return NULL;
-  return g->gsmem.membase.loads;
+  return &g->gsmem.membase.vuse;
 }
 
+/* Return the single VDEF operand of the statement G.  */
 
-/* Return the set of symbols stored by statement G.  Each element of
-   the set is the DECL_UID of the corresponding symbol.  */
-
-static inline bitmap
-gimple_stored_syms (const_gimple g)
+static inline tree *
+gimple_vdef_ptr (gimple g)
 {
   if (!gimple_has_mem_ops (g))
     return NULL;
-  return g->gsmem.membase.stores;
+  return &g->gsmem.membase.vdef;
+}
+
+/* Set the single VUSE operand of the statement G.  */
+
+static inline void
+gimple_set_vuse (gimple g, tree vuse)
+{
+  gcc_assert (gimple_has_mem_ops (g));
+  g->gsmem.membase.vuse = vuse;
+}
+
+/* Set the single VDEF operand of the statement G.  */
+
+static inline void
+gimple_set_vdef (gimple g, tree vdef)
+{
+  gcc_assert (gimple_has_mem_ops (g));
+  g->gsmem.membase.vdef = vdef;
 }
 
 
@@ -1486,19 +1509,10 @@ gimple_set_has_volatile_ops (gimple stmt, bool volatilep)
 static inline bool
 gimple_references_memory_p (gimple stmt)
 {
-  return gimple_has_mem_ops (stmt) && stmt->gsbase.references_memory_p;
+  return gimple_has_mem_ops (stmt) && gimple_vuse (stmt);
 }
 
 
-/* Set the REFERENCES_MEMORY_P flag for STMT to MEM_P.  */
-
-static inline void
-gimple_set_references_memory (gimple stmt, bool mem_p)
-{
-  if (gimple_has_mem_ops (stmt))
-    stmt->gsbase.references_memory_p = (unsigned) mem_p;
-}
-
 /* Return the subcode for OMP statement S.  */
 
 static inline unsigned
index b732b40..e106f48 100644 (file)
@@ -4119,7 +4119,7 @@ rename_variables_in_stmt (gimple stmt, htab_t map)
   ssa_op_iter iter;
   use_operand_p use_p;
 
-  FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
+  FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES)
     {
       tree use = USE_FROM_PTR (use_p);
       tree new_name = get_new_name_from_old_name (map, use);
@@ -4238,8 +4238,6 @@ expand_scalar_variables_expr (tree type, tree op0, enum tree_code code,
            tree new_name = force_gimple_operand_gsi (gsi, expr, true, NULL,
                                                      true, GSI_SAME_STMT);
 
-           set_symbol_mem_tag (SSA_NAME_VAR (new_name),
-                               symbol_mem_tag (SSA_NAME_VAR (old_name)));
            return fold_build1 (code, type, new_name);
          }
 
@@ -4479,7 +4477,7 @@ graphite_copy_stmts_from_block (basic_block bb, basic_block new_bb, htab_t map)
         operands.  */
       copy = gimple_copy (stmt);
       gsi_insert_after (&gsi_tgt, copy, GSI_NEW_STMT);
-      mark_symbols_for_renaming (copy);
+      mark_sym_for_renaming (gimple_vop (cfun));
 
       region = lookup_stmt_eh_region (stmt);
       if (region >= 0)
@@ -4488,7 +4486,7 @@ graphite_copy_stmts_from_block (basic_block bb, basic_block new_bb, htab_t map)
 
       /* Create new names for all the definitions created by COPY and
         add replacement mappings for each new name.  */
-      FOR_EACH_SSA_DEF_OPERAND (def_p, copy, op_iter, SSA_OP_DEF)
+      FOR_EACH_SSA_DEF_OPERAND (def_p, copy, op_iter, SSA_OP_ALL_DEFS)
        {
          tree old_name = DEF_FROM_PTR (def_p);
          tree new_name = create_new_def_for (old_name, copy, def_p);
@@ -4708,8 +4706,8 @@ translate_clast (scop_p scop, struct loop *context_loop,
                                               next_e, map);
       htab_delete (map);
       loop_iv_stack_remove_constants (ivstack);
-      update_ssa (TODO_update_ssa);
       recompute_all_dominators ();
+      update_ssa (TODO_update_ssa);
       graphite_verify ();
       return translate_clast (scop, context_loop, stmt->next, next_e, ivstack);
     }
index 3fae029..137dd66 100644 (file)
@@ -969,6 +969,8 @@ ipcp_update_callgraph (void)
                
                new_stmt = gimple_call_copy_skip_args (cs->call_stmt,
                                                       args_to_skip);
+               if (gimple_vdef (new_stmt))
+                 SSA_NAME_DEF_STMT (gimple_vdef (new_stmt)) = new_stmt;
                gsi = gsi_for_stmt (cs->call_stmt);
                gsi_replace (&gsi, new_stmt, true);
                cgraph_set_call_stmt (cs, new_stmt);
index 21ecfd5..a8c4b1b 100644 (file)
@@ -140,8 +140,6 @@ static inline void
 check_decl (funct_state local, 
            tree t, bool checking_write)
 {
-  if (MTAG_P (t))
-    return;
   /* Do not want to do anything with volatile except mark any
      function that uses one to be not const or pure.  */
   if (TREE_THIS_VOLATILE (t)) 
@@ -377,26 +375,59 @@ check_call (funct_state local, gimple call, bool ipa)
   /* Direct functions calls are handled by IPA propagation.  */
 }
 
-/* Look into pointer pointed to by GSIP and figure out what interesting side effects
-   it have.  */
+/* Look into pointer pointed to by GSIP and figure out what interesting side
+   effects it has.  */
 static void
 check_stmt (gimple_stmt_iterator *gsip, funct_state local, bool ipa)
 {
   gimple stmt = gsi_stmt (*gsip);
   unsigned int i = 0;
-  bitmap_iterator bi;
 
   if (dump_file)
     {
       fprintf (dump_file, "  scanning: ");
       print_gimple_stmt (dump_file, stmt, 0, 0);
     }
-  if (gimple_loaded_syms (stmt))
-    EXECUTE_IF_SET_IN_BITMAP (gimple_loaded_syms (stmt), 0, i, bi)
-      check_decl (local, referenced_var_lookup (i), false);
-  if (gimple_stored_syms (stmt))
-    EXECUTE_IF_SET_IN_BITMAP (gimple_stored_syms (stmt), 0, i, bi)
-      check_decl (local, referenced_var_lookup (i), true);
+
+  /* Look for direct loads and stores.  */
+  if (gimple_has_lhs (stmt))
+    {
+      tree lhs = get_base_address (gimple_get_lhs (stmt));
+      if (lhs && DECL_P (lhs))
+       check_decl (local, lhs, true);
+    }
+  if (gimple_assign_single_p (stmt))
+    {
+      tree rhs = get_base_address (gimple_assign_rhs1 (stmt));
+      if (rhs && DECL_P (rhs))
+       check_decl (local, rhs, false);
+    }
+  else if (is_gimple_call (stmt))
+    {
+      for (i = 0; i < gimple_call_num_args (stmt); ++i)
+       {
+         tree rhs = get_base_address (gimple_call_arg (stmt, i));
+         if (rhs && DECL_P (rhs))
+           check_decl (local, rhs, false);
+       }
+    }
+  else if (gimple_code (stmt) == GIMPLE_ASM)
+    {
+      for (i = 0; i < gimple_asm_ninputs (stmt); ++i)
+       {
+         tree op = TREE_VALUE (gimple_asm_input_op (stmt, i));
+         op = get_base_address (op);
+         if (op && DECL_P (op))
+           check_decl (local, op, false);
+       }
+      for (i = 0; i < gimple_asm_noutputs (stmt); ++i)
+       {
+         tree op = TREE_VALUE (gimple_asm_output_op (stmt, i));
+         op = get_base_address (op);
+         if (op && DECL_P (op))
+           check_decl (local, op, true);
+       }
+    }
 
   if (gimple_code (stmt) != GIMPLE_CALL
       && stmt_could_throw_p (stmt))
index a9afd45..4bc49cf 100644 (file)
@@ -433,33 +433,51 @@ scan_stmt_for_static_refs (gimple_stmt_iterator *gsip,
   if (fn)
     local = get_reference_vars_info (fn)->local;
 
-  if (gimple_loaded_syms (stmt))
-    EXECUTE_IF_SET_IN_BITMAP (gimple_loaded_syms (stmt), 0, i, bi)
-      mark_load (local, referenced_var_lookup (i));
-  if (gimple_stored_syms (stmt))
-    EXECUTE_IF_SET_IN_BITMAP (gimple_stored_syms (stmt), 0, i, bi)
-      mark_store (local, referenced_var_lookup (i));
-  if (gimple_addresses_taken (stmt))
-    EXECUTE_IF_SET_IN_BITMAP (gimple_addresses_taken (stmt), 0, i, bi)
-      mark_address_taken (referenced_var_lookup (i));
-
-  switch (gimple_code (stmt))
+  /* Look for direct loads and stores.  */
+  if (gimple_has_lhs (stmt))
+    {
+      tree lhs = get_base_address (gimple_get_lhs (stmt));
+      if (lhs && DECL_P (lhs))
+        mark_store (local, lhs);
+    }
+  if (gimple_assign_single_p (stmt))
     {
-    case GIMPLE_CALL:
+      tree rhs = get_base_address (gimple_assign_rhs1 (stmt));
+      if (rhs && DECL_P (rhs))
+       mark_load (local, rhs);
+    }
+  else if (is_gimple_call (stmt))
+    {
+      for (i = 0; i < gimple_call_num_args (stmt); ++i)
+       {
+         tree rhs = get_base_address (gimple_call_arg (stmt, i));
+         if (rhs && DECL_P (rhs))
+           mark_load (local, rhs);
+       }
       check_call (local, stmt);
-      break;
-      
-    case GIMPLE_ASM:
+    }
+  else if (gimple_code (stmt) == GIMPLE_ASM)
+    {
+      for (i = 0; i < gimple_asm_ninputs (stmt); ++i)
+       {
+         tree op = TREE_VALUE (gimple_asm_input_op (stmt, i));
+         op = get_base_address (op);
+         if (op && DECL_P (op))
+           mark_load (local, op);
+       }
+      for (i = 0; i < gimple_asm_noutputs (stmt); ++i)
+       {
+         tree op = TREE_VALUE (gimple_asm_output_op (stmt, i));
+         op = get_base_address (op);
+         if (op && DECL_P (op))
+           mark_store (local, op);
+       }
       check_asm_memory_clobber (local, stmt);
-      break;
-
-    /* We used to check nonlocal labels here and set them as potentially modifying
-       everything.  This is not needed, since we can get to nonlocal label only
-       from callee and thus we will get info propagated.  */
-
-    default:
-      break;
     }
+
+  if (gimple_addresses_taken (stmt))
+    EXECUTE_IF_SET_IN_BITMAP (gimple_addresses_taken (stmt), 0, i, bi)
+      mark_address_taken (referenced_var_lookup (i));
   
   return NULL;
 }
index ab70c98..9ca5364 100644 (file)
@@ -495,8 +495,6 @@ static void
 finalize_var_creation (tree new_decl)
 {
   add_referenced_var (new_decl);  
-  if (is_global_var (new_decl))
-    mark_call_clobbered (new_decl, ESCAPE_UNKNOWN);
   mark_sym_for_renaming (new_decl); 
 }
 
@@ -1249,6 +1247,13 @@ create_general_new_stmt (struct access_site *acc, tree new_type)
   gimple new_stmt = gimple_copy (old_stmt);
   unsigned i;
 
+  /* We are really building a new stmt, clear the virtual operands.  */
+  if (gimple_has_mem_ops (new_stmt))
+    {
+      gimple_set_vuse (new_stmt, NULL_TREE);
+      gimple_set_vdef (new_stmt, NULL_TREE);
+    }
+
   for (i = 0; VEC_iterate (tree, acc->vars, i, var); i++)
     {
       tree *pos;
index 07b9469..852be11 100644 (file)
@@ -2142,7 +2142,7 @@ can_put_in_inner_loop (struct loop *inner, gimple stmt)
   use_operand_p use_p;
   
   gcc_assert (is_gimple_assign (stmt));
-  if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS)
+  if (gimple_vuse (stmt)
       || !stmt_invariant_in_loop_p (inner, stmt))
     return false;
   
@@ -2167,7 +2167,7 @@ can_put_after_inner_loop (struct loop *loop, gimple stmt)
   imm_use_iterator imm_iter;
   use_operand_p use_p;
 
-  if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
+  if (gimple_vuse (stmt))
     return false;
   
   FOR_EACH_IMM_USE_FAST (use_p, imm_iter, gimple_assign_lhs (stmt))
@@ -2536,8 +2536,6 @@ perfect_nestify (struct loop *loop,
                 incremented when we do.  */
              for (bsi = gsi_start_bb (bbs[i]); !gsi_end_p (bsi);)
                { 
-                 ssa_op_iter i;
-                 tree n;
                  gimple stmt = gsi_stmt (bsi);
                  
                  if (stmt == exit_condition
@@ -2553,12 +2551,12 @@ perfect_nestify (struct loop *loop,
                     VEC_index (tree, lbounds, 0), replacements, &firstbsi);
 
                  gsi_move_before (&bsi, &tobsi);
-                 
+
                  /* If the statement has any virtual operands, they may
                     need to be rewired because the original loop may
                     still reference them.  */
-                 FOR_EACH_SSA_TREE_OPERAND (n, stmt, i, SSA_OP_ALL_VIRTUALS)
-                   mark_sym_for_renaming (SSA_NAME_VAR (n));
+                 if (gimple_vuse (stmt))
+                   mark_sym_for_renaming (gimple_vop (cfun));
                }
            }
          
index b96da5f..ec02b5f 100644 (file)
@@ -3495,6 +3495,8 @@ expand_omp_taskreg (struct omp_region *region)
          if (changed)
            cleanup_tree_cfg ();
        }
+      if (gimple_in_ssa_p (cfun))
+       update_ssa (TODO_update_ssa);
       current_function_decl = save_current;
       pop_cfun ();
     }
index e318790..2c7531e 100644 (file)
@@ -777,8 +777,6 @@ void
 decode_options (unsigned int argc, const char **argv)
 {
   static bool first_time_p = true;
-  static int initial_max_aliased_vops;
-  static int initial_avg_aliased_vops;
   static int initial_min_crossjump_insns;
   static int initial_max_fields_for_field_sensitive;
   static int initial_loop_invariant_max_bbs_in_loop;
@@ -798,8 +796,6 @@ decode_options (unsigned int argc, const char **argv)
       lang_hooks.initialize_diagnostics (global_dc);
 
       /* Save initial values of parameters we reset.  */
-      initial_max_aliased_vops = MAX_ALIASED_VOPS;
-      initial_avg_aliased_vops = AVG_ALIASED_VOPS;
       initial_min_crossjump_insns
        = compiler_params[PARAM_MIN_CROSSJUMP_INSNS].value;
       initial_max_fields_for_field_sensitive
@@ -907,11 +903,6 @@ decode_options (unsigned int argc, const char **argv)
   flag_tree_switch_conversion = 1;
   flag_ipa_cp = opt2;
 
-  /* Allow more virtual operators to increase alias precision.  */
-
-  set_param_value ("max-aliased-vops",
-                  (opt2) ? 500 : initial_max_aliased_vops);
-
   /* Track fields in field-sensitive alias analysis.  */
   set_param_value ("max-fields-for-field-sensitive",
                   (opt2) ? 100 : initial_max_fields_for_field_sensitive);
@@ -931,13 +922,6 @@ decode_options (unsigned int argc, const char **argv)
   if (flag_ipa_cp_clone)
     flag_ipa_cp = 1;
 
-  /* Allow even more virtual operators.  Max-aliased-vops was set above for
-     -O2, so don't reset it unless we are at -O3.  */
-  if (opt3)
-    set_param_value ("max-aliased-vops", 1000);
-
-  set_param_value ("avg-aliased-vops", (opt3) ? 3 : initial_avg_aliased_vops);
-
   /* Just -O1/-O0 optimizations.  */
   opt1_max = (optimize <= 1);
   align_loops = opt1_max;
index 3f7b2e7..652bbb2 100644 (file)
@@ -537,16 +537,6 @@ DEFPARAM(PARAM_MAX_RELOAD_SEARCH_INSNS,
         "The maximum number of instructions to search backward when looking for equivalent reload",
         100, 0, 0)
 
-DEFPARAM(PARAM_MAX_ALIASED_VOPS,
-         "max-aliased-vops",
-        "The maximum number of virtual operators that a function is allowed to have before triggering memory partitioning heuristics",
-        100, 0, 0)
-
-DEFPARAM(PARAM_AVG_ALIASED_VOPS,
-        "avg-aliased-vops",
-        "The average number of virtual operators that memory statements are allowed to have before triggering memory partitioning heuristics",
-        1, 0, 0)
-
 DEFPARAM(PARAM_MAX_SCHED_REGION_BLOCKS,
         "max-sched-region-blocks",
         "The maximum number of blocks in a region to be considered for interblock scheduling",
index fb2dad5..a607fb0 100644 (file)
@@ -140,10 +140,6 @@ typedef enum compiler_param
   PARAM_VALUE (PARAM_SMS_DFA_HISTORY)
 #define SMS_LOOP_AVERAGE_COUNT_THRESHOLD \
   PARAM_VALUE (PARAM_SMS_LOOP_AVERAGE_COUNT_THRESHOLD)
-#define MAX_ALIASED_VOPS \
-  PARAM_VALUE (PARAM_MAX_ALIASED_VOPS)
-#define AVG_ALIASED_VOPS \
-  PARAM_VALUE (PARAM_AVG_ALIASED_VOPS)
 #define INTEGER_SHARE_LIMIT \
   PARAM_VALUE (PARAM_INTEGER_SHARE_LIMIT)
 #define MAX_LAST_VALUE_RTL \
index 3d7b18c..f19b8dd 100644 (file)
@@ -543,7 +543,6 @@ init_optimization_passes (void)
       NEXT_PASS (pass_expand_omp);
 
       NEXT_PASS (pass_referenced_vars);
-      NEXT_PASS (pass_reset_cc_flags);
       NEXT_PASS (pass_build_ssa);
       NEXT_PASS (pass_early_warn_uninitialized);
       NEXT_PASS (pass_all_early_optimizations);
@@ -560,7 +559,6 @@ init_optimization_passes (void)
          NEXT_PASS (pass_copy_prop);
          NEXT_PASS (pass_merge_phi);
          NEXT_PASS (pass_cd_dce);
-         NEXT_PASS (pass_simple_dse);
          NEXT_PASS (pass_tail_recursion);
          NEXT_PASS (pass_convert_switch);
           NEXT_PASS (pass_cleanup_eh);
@@ -937,7 +935,7 @@ execute_function_todo (void *data)
         SSA form to become out-of-date (see PR 22037).  So, even
         if the parent pass had not scheduled an SSA update, we may
         still need to do one.  */
-      if (!(flags & TODO_update_ssa_any) && need_ssa_update_p ())
+      if (!(flags & TODO_update_ssa_any) && need_ssa_update_p (cfun))
        flags |= TODO_update_ssa;
     }
 
@@ -948,8 +946,13 @@ execute_function_todo (void *data)
       cfun->last_verified &= ~TODO_verify_ssa;
     }
   
+  if (flags & TODO_update_address_taken)
+    execute_update_addresses_taken (true);
+
   if (flags & TODO_rebuild_alias)
     {
+      if (!(flags & TODO_update_address_taken))
+       execute_update_addresses_taken (true);
       compute_may_aliases ();
       cfun->curr_properties |= PROP_alias;
     }
@@ -1021,7 +1024,8 @@ static void
 execute_todo (unsigned int flags)
 {
 #if defined ENABLE_CHECKING
-  if (need_ssa_update_p ())
+  if (cfun
+      && need_ssa_update_p (cfun))
     gcc_assert (flags & TODO_update_ssa_any);
 #endif
 
@@ -1265,6 +1269,8 @@ execute_one_pass (struct opt_pass *pass)
      This is a hack until the new folder is ready.  */
   in_gimple_form = (cfun && (cfun->curr_properties & PROP_trees)) != 0;
 
+  initializing_dump = pass_init_dump_file (pass);
+
   /* Run pre-pass verification.  */
   execute_todo (pass->todo_flags_start);
 
@@ -1273,8 +1279,6 @@ execute_one_pass (struct opt_pass *pass)
                   (void *)(size_t)pass->properties_required);
 #endif
 
-  initializing_dump = pass_init_dump_file (pass);
-
   /* If a timevar is present, start it.  */
   if (pass->tv_id)
     timevar_push (pass->tv_id);
index a73f8af..77f7ed8 100644 (file)
@@ -1,3 +1,62 @@
+2009-04-03  Richard Guenther  <rguenther@suse.de>
+
+       PR middle-end/13146
+       PR tree-optimization/23940
+       PR tree-optimization/33237
+       PR middle-end/33974
+       PR middle-end/34093
+       PR tree-optimization/36201
+       PR tree-optimization/36230
+       PR tree-optimization/38049
+       PR tree-optimization/38207
+       PR tree-optimization/38230
+       PR tree-optimization/38301
+       PR tree-optimization/38585
+       PR middle-end/38895
+       PR tree-optimization/38985
+       PR tree-optimization/39299
+       * gcc.dg/pr19633-1.c: Adjust.
+       * gcc.dg/torture/pta-callused-1.c: Likewise.
+       * gcc.dg/torture/pr39074-2.c: Likewise.
+       * gcc.dg/torture/pr39074.c: Likewise.
+       * gcc.dg/torture/pta-ptrarith-3.c: New testcase.
+       * gcc.dg/torture/pr30375.c: Adjust.
+       * gcc.dg/torture/pr33563.c: Likewise.
+       * gcc.dg/torture/pr33870.c: Likewise.
+       * gcc.dg/torture/pr33560.c: Likewise.
+       * gcc.dg/torture/pta-structcopy-1.c: New testcase.
+       * gcc.dg/torture/ssa-pta-fn-1.c: Likewise.
+       * gcc.dg/tree-ssa/alias-15.c: Remove.
+       * gcc.dg/tree-ssa/ssa-dce-4.c: New testcase.
+       * gcc.dg/tree-ssa/pr26421.c: Adjust.
+       * gcc.dg/tree-ssa/ssa-fre-10.c: XFAIL.
+       * gcc.dg/tree-ssa/ssa-dce-5.c: New testcase.
+       * gcc.dg/tree-ssa/pr23382.c: Adjust.
+       * gcc.dg/tree-ssa/ssa-fre-20.c: New testcase.
+       * gcc.dg/tree-ssa/alias-16.c: Adjust.
+       * gcc.dg/tree-ssa/ssa-fre-13.c: Likewise.
+       * gcc.dg/tree-ssa/ssa-fre-14.c: Likewise.
+       * gcc.dg/tree-ssa/alias-18.c: Likewise.
+       * gcc.dg/tree-ssa/ssa-fre-15.c: Likewise.
+       * gcc.dg/tree-ssa/ssa-lim-3.c: Likewise.
+       * gcc.dg/tree-ssa/alias-19.c: Likewise.
+       * gcc.dg/tree-ssa/pta-ptrarith-1.c: New testcase.
+       * gcc.dg/tree-ssa/pr13146.c: Likewise.
+       * gcc.dg/tree-ssa/ssa-pre-23.c: Likewise.
+       * gcc.dg/tree-ssa/pta-ptrarith-2.c: Likewise.
+       * gcc.dg/tree-ssa/ssa-fre-18.c: Likewise.
+       * gcc.dg/tree-ssa/ssa-pre-24.c: New XFAILed testcase.
+       * gcc.dg/tree-ssa/ssa-fre-19.c: New testcase.
+       * gcc.dg/tree-ssa/alias-20.c: Likewise.
+       * gcc.dg/tree-ssa/ssa-dse-12.c: Likewise.
+       * gcc.dg/tree-ssa/pr38895.c: Likewise.
+       * gcc.dg/uninit-B.c: XFAIL.
+       * gcc.dg/vect/no-vfa-vect-43.c: Adjust.
+       * gcc.dg/uninit-pr19430.c: XFAIL.
+       * g++.dg/tree-ssa/pr13146.C: New testcase.
+       * g++.dg/opt/pr36187.C: Adjust.
+       * g++.dg/torture/20090329-1.C: New testcase.
+
 2009-04-02  Chao-ying Fu  <fu@mips.com>
 
        * gcc.target/mips/interrupt_handler.c: New test.
index fdb468d..9116694 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-O2 --param max-aliased-vops=20" } */
+/* { dg-options "-O2" } */
 
 extern "C" void abort (void);
 enum SbxDataType { SbxINTEGER, SbxDECIMAL, SbxBYREF = 0x4000 };
diff --git a/gcc/testsuite/g++.dg/torture/20090329-1.C b/gcc/testsuite/g++.dg/torture/20090329-1.C
new file mode 100644 (file)
index 0000000..0274a19
--- /dev/null
@@ -0,0 +1,59 @@
+/* { dg-do compile } */
+
+struct input_iterator_tag { };
+template<typename _Category, typename _Tp, typename _Distance = long, typename _Pointer = _Tp*, typename _Reference = _Tp&>
+struct iterator {
+    typedef _Category iterator_category;
+};
+template<typename _Iterator> struct iterator_traits {
+    typedef typename _Iterator::iterator_category iterator_category;
+};
+template<typename, typename> struct __lc_rai {
+    template<typename _II1, typename _II2>
+       static _II1 __newlast1(_II1, _II1 __last1, _II2, _II2) {
+           return __last1;
+       }
+    template<typename _II> 
+       static bool __cnd2(_II __first, _II __last) {
+           return __first != __last;
+       }
+};
+template<typename _II1, typename _II2, typename _Compare>
+bool lexicographical_compare(_II1 __first1, _II1 __last1, _II2 __first2,
+                            _II2 __last2, _Compare __comp) {
+    typedef typename iterator_traits<_II1>::iterator_category _Category1;
+    typedef typename iterator_traits<_II2>::iterator_category _Category2;
+    typedef __lc_rai<_Category1, _Category2> __rai_type;
+    __last1 = __rai_type::__newlast1(__first1, __last1, __first2, __last2);
+    for (;
+        __first1 != __last1 && __rai_type::__cnd2(__first2, __last2);
+        ++__first1, ++__first2) {
+       if (__comp(*__first1, *__first2)) return true;
+    }
+}
+void __assert_fail () throw () __attribute__ ((__noreturn__));
+template<typename T> struct BoundsContainer { };
+template<class T> class input_iterator_wrapper : public iterator<input_iterator_tag, T, long, T*, T&> {
+public:
+    typedef BoundsContainer<T> ContainerType;
+    T* ptr;
+    ContainerType* SharedInfo;
+    input_iterator_wrapper(const input_iterator_wrapper& in) : ptr(in.ptr), SharedInfo(in.SharedInfo) { }
+    bool operator==(const input_iterator_wrapper& in) const {
+       (static_cast<void> ((SharedInfo != __null
+                            && SharedInfo == in.SharedInfo)
+                           ? 0 : (__assert_fail (), 0)));
+    }
+    bool operator!=(const input_iterator_wrapper& in) const {
+       return !(*this == in);
+    }
+    T& operator*() const { }
+    input_iterator_wrapper& operator++() { }
+};
+struct X { };
+bool predicate(const X&, const X&) {
+    return true;
+}
+bool test2(input_iterator_wrapper<X>& x) {
+    return lexicographical_compare(x, x, x, x, predicate);
+}
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr13146.C b/gcc/testsuite/g++.dg/tree-ssa/pr13146.C
new file mode 100644 (file)
index 0000000..62447c1
--- /dev/null
@@ -0,0 +1,74 @@
+/* { dg-do link } */
+/* { dg-options "-O -fstrict-aliasing" } */
+
+class first
+{
+public:
+  double d;
+  int f1;
+};
+
+class middle : public first
+{
+};
+
+class second : public middle
+{
+public:
+  int f2;
+  short a;
+};
+
+class third
+{
+public:
+  char a;
+  char b;
+};
+
+class multi: public third, public second
+{
+public:
+  short s;
+  char f3;
+};
+
+extern void link_error ();
+
+void
+foo (first *s1, second *s2)
+{
+  s1->f1 = 0;
+  s2->f2 = 0;
+  s1->f1++;
+  s2->f2++;
+  s1->f1++;
+  s2->f2++;
+  if (s1->f1 != 2)
+    link_error ();
+}
+
+void
+bar (first *s1, multi *s3)
+{
+  s1->f1 = 0;
+  s3->f3 = 0;
+  s1->f1++;
+  s3->f3++;
+  s1->f1++;
+  s3->f3++;
+  if (s1->f1 != 2)
+    link_error ();
+}
+
+
+int
+main()
+{
+  first a;
+  second b;
+  multi c;
+  foo (&a, &b);
+  bar (&a, &c);
+  return 0;
+}
index 6370ff5..c05e46a 100644 (file)
@@ -1,9 +1,5 @@
 /* { dg-do run } */
-
-/* The max-aliased-vops setting is a temporary workaround to avoid the
-   random failures as described in PR 30194.  This test case does not
-   need alias sets bigger than 13 elements.  */
-/* { dg-options "-O2 --param max-aliased-vops=15" } */
+/* { dg-options "-O2" } */
 
 extern void abort (void);
 
index ea63f97..435c38f 100644 (file)
@@ -1,5 +1,4 @@
 /* { dg-do run } */
-/* { dg-options "--param max-aliased-vops=0" } */
 
 typedef struct _s {
     int a;
index 5b2359b..7eea1e3 100644 (file)
@@ -1,5 +1,4 @@
 /* { dg-do run } */
-/* { dg-options "--param max-aliased-vops=0" } */
 
 struct T
 {
index 47907db..33e7852 100644 (file)
@@ -1,5 +1,4 @@
 /* { dg-do run } */
-/* { dg-options "--param max-aliased-vops=0" } */
 
 struct T
 {
index 519efd3..9c0e30d 100644 (file)
@@ -1,5 +1,4 @@
 /* { dg-do run } */
-/* { dg-options "--param max-aliased-vops=1" } */
 
 struct X {
   int i;
index 89f7ebf..a90c564 100644 (file)
@@ -30,5 +30,5 @@ int main()
   return 0;
 }
 
-/* { dg-final { scan-tree-dump "y.._., name memory tag: NMT..., is dereferenced, points-to vars: { i }" "alias" } } */
+/* { dg-final { scan-tree-dump "y.._., points-to vars: { i }" "alias" } } */
 /* { dg-final { cleanup-tree-dump "alias" } } */
index cc37c8e..7be7e22 100644 (file)
@@ -27,5 +27,5 @@ int main()
   return 0;
 }
 
-/* { dg-final { scan-tree-dump "y.._., name memory tag: NMT..., is dereferenced, points-to vars: { i }" "alias" } } */
+/* { dg-final { scan-tree-dump "y.._., points-to vars: { i }" "alias" } } */
 /* { dg-final { cleanup-tree-dump "alias" } } */
index dfe994b..dfbde86 100644 (file)
@@ -21,5 +21,5 @@ int main()
   return 0;
 }
 
-/* { dg-final { scan-tree-dump "p.._., name memory tag: NMT..., is dereferenced, points-to vars: { i j }" "alias" } } */
+/* { dg-final { scan-tree-dump "p.._., points-to vars: { i j }" "alias" } } */
 /* { dg-final { cleanup-tree-dump "alias" } } */
diff --git a/gcc/testsuite/gcc.dg/torture/pta-ptrarith-3.c b/gcc/testsuite/gcc.dg/torture/pta-ptrarith-3.c
new file mode 100644 (file)
index 0000000..6c08319
--- /dev/null
@@ -0,0 +1,37 @@
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-alias" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+
+extern void abort (void);
+struct X {
+  int *p;
+  int *q;
+  int *r;
+};
+int __attribute__((noinline))
+foo(int i, int j, int k, int off)
+{
+  struct X x;
+  int **p, *q;
+  x.p = &i;
+  x.q = &j;
+  x.r = &k;
+  p = &x.q;
+  p += off;
+  /* *p points to { i, j, k } */
+  q = *p;
+  return *q;
+}
+int main()
+{
+  if (foo(1, 2, 3, -1) != 1)
+    abort ();
+  if (foo(1, 2, 3, 0) != 2)
+    abort ();
+  if (foo(1, 2, 3, 1) != 3)
+    abort ();
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump "q_., points-to vars: { i j k }" "alias" } } */
+/* { dg-final { cleanup-tree-dump "alias" } } */
diff --git a/gcc/testsuite/gcc.dg/torture/pta-structcopy-1.c b/gcc/testsuite/gcc.dg/torture/pta-structcopy-1.c
new file mode 100644 (file)
index 0000000..bdb2acb
--- /dev/null
@@ -0,0 +1,34 @@
+/* { dg-do run } */
+/* { dg-options "-fno-tree-sra -fdump-tree-alias" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+
+struct X
+{
+  long l1;
+  struct Y
+    {
+      long l2;
+      int *p;
+    } y;
+};
+int i;
+static int
+foo (struct X *x)
+{
+  struct Y y = x->y;
+  *y.p = 0;
+  i = 1;
+  return *y.p;
+}
+extern void abort (void);
+int main()
+{
+  struct X x;
+  x.y.p = &i;
+  if (foo(&x) != 1)
+    abort ();
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump "points-to vars: { i }" "alias" } } */
+/* { dg-final { cleanup-tree-dump "alias" } } */
diff --git a/gcc/testsuite/gcc.dg/torture/ssa-pta-fn-1.c b/gcc/testsuite/gcc.dg/torture/ssa-pta-fn-1.c
new file mode 100644 (file)
index 0000000..21d36dc
--- /dev/null
@@ -0,0 +1,61 @@
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-alias" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+
+extern void abort (void);
+int *glob;
+
+int * __attribute__((noinline,const))
+foo_const(int *p) { return p; }
+
+int * __attribute__((noinline,pure))
+foo_pure(int *p) { return glob; }
+
+int * __attribute__((noinline))
+foo_normal(int *p) { glob = p; return p; }
+
+void test_const(void)
+{
+  int i;
+  int *p = &i;
+  int *q_const = foo_const(p);
+  *p = 1;
+  *q_const = 2;
+  if (*p != 2)
+    abort ();
+}
+
+void test(void)
+{
+  int i;
+  int *p = &i;
+  int *q_normal = foo_normal(p);
+  *p = 1;
+  *q_normal = 2;
+  if (*p != 2)
+    abort ();
+}
+
+void test_pure(void)
+{
+  int i;
+  int *p = &i;
+  int *q_pure = foo_pure(p);
+  *p = 1;
+  *q_pure = 2;
+  if (*p != 2)
+    abort ();
+}
+
+int main()
+{
+  test_const();
+  test();
+  test_pure();
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump "q_const_., points-to non-local, points-to vars: { i }" "alias" } } */
+/* { dg-final { scan-tree-dump "q_pure_., points-to non-local, points-to escaped, points-to vars: { i }" "alias" } } */
+/* { dg-final { scan-tree-dump "q_normal_., points-to non-local, points-to escaped, points-to vars: { }" "alias" } } */
+/* { dg-final { cleanup-tree-dump "alias" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-15.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-15.c
deleted file mode 100644 (file)
index 617af0f..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/* { dg-do compile } */
-/* { dg-options "-O -fno-early-inlining -fdump-tree-alias-vops-details" } */
-
-struct foo {
-  int a;
-  struct X {
-    int b[4];
-  } b;
-} m;
-static inline struct X *wrap(struct X *p) { return p; }
-int test2(void)
-{
-  struct X *p = wrap(&m.b);
-  /* Both memory references need to alias the same tags.  */
-  return p->b[3] - m.b.b[3];
-}
-
-/* { dg-final { scan-tree-dump-times "VUSE <m_.\\\(D\\\)>" 2 "alias" } } */
-/* { dg-final { cleanup-tree-dump "alias" } } */
index cf10fa9..c71486c 100644 (file)
@@ -1,9 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-O --param max-aliased-vops=1" } */
 
-/* Compile with -O --param max-aliased-vops=1.  This partitions all
-   the initial SFTs for 'm' which was causing the operand scanner to
-   miss adding the right SFTs to p->b[2].  */
 extern void abort (void);
 
 struct X {
index 84d884e..c78bceb 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-fre-details -fdump-tree-optimized --param max-aliased-vops=0" } */
+/* { dg-options "-O2 -fdump-tree-fre-details -fdump-tree-optimized" } */
 
 struct A {
   int i;
index b92df43..7b36890 100644 (file)
@@ -26,6 +26,5 @@ int main()
 }
 
 /* { dg-final { scan-tree-dump "q_. = { a b }" "alias" } } */
-/* { dg-final { scan-tree-dump "q_., name memory tag: NMT..., is dereferenced, points-to vars: { a b }" "alias" } } */
-/* { dg-final { scan-tree-dump "# VUSE <a_.\\\(D\\\), b_.>" "alias" } } */
+/* { dg-final { scan-tree-dump "q_., points-to vars: { a b }" "alias" } } */
 /* { dg-final { cleanup-tree-dump "alias" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-20.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-20.c
new file mode 100644 (file)
index 0000000..7991c52
--- /dev/null
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fstrict-aliasing -fdump-tree-optimized" } */
+
+struct S { float f; int i; };
+struct R { int x; int i; };
+
+/* Strict-aliasing rules say that int and float do not alias.  */
+int bar(struct S *s, int *i)
+{
+  *i = 0;
+  s->f = 1.0;
+  return *i;
+}
+
+/* Strict-aliasing rules say that S and R do not alias.  */
+int foo(struct S *s, struct R *r)
+{
+  r->i = 0;
+  s->i = 1;
+  return r->i;
+}
+
+/* { dg-final { scan-tree-dump-times "return 0;" 2 "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr13146.c b/gcc/testsuite/gcc.dg/tree-ssa/pr13146.c
new file mode 100644 (file)
index 0000000..b556457
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fstrict-aliasing -fdump-tree-optimized" } */
+
+struct A
+{
+  int i;
+};
+struct B
+{
+  struct A a;
+  int j;
+};
+
+int foo (struct A *p, struct B *q)
+{
+  p->i = 0;
+  q->j = 1;
+  return p->i;
+}
+
+/* { dg-final { scan-tree-dump "return 0;" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
index 331e01b..fd74af8 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */ 
-/* { dg-options "-O2 -fdump-tree-alias-vops" } */
+/* { dg-options "-O2 -fdump-tree-pre-details" } */
 struct a
 {
   int length;
@@ -13,5 +13,5 @@ int f(void)
    struct a *a = malloc(sizeof(struct a));
    return a->length;
 }
-/* { dg-final { scan-tree-dump-times "VDEF <HEAP" 1 "alias"} } */
-/* { dg-final { cleanup-tree-dump "alias" } } */
+/* { dg-final { scan-tree-dump-times "Variable: HEAP" 1 "pre"} } */
+/* { dg-final { cleanup-tree-dump "pre" } } */
index 73db85c..70f1231 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-alias-vops" } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
 
 typedef struct {
   int i;
@@ -18,5 +18,5 @@ int foo(void)
 
 /* Verify the call clobbers all of a.  */
 
-/* { dg-final { scan-tree-dump-times "VDEF <a_" 2 "alias" } } */
-/* { dg-final { cleanup-tree-dump "alias" } } */
+/* { dg-final { scan-tree-dump-not "return 1;" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr38895.c b/gcc/testsuite/gcc.dg/tree-ssa/pr38895.c
new file mode 100644 (file)
index 0000000..0a96e53
--- /dev/null
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fstrict-aliasing -fdump-tree-optimized" } */
+
+struct A {
+  int i;
+  int j;
+};
+struct B {
+  struct A a1;
+  struct A a2;
+};
+struct C {
+  struct A a1;
+  struct B b;
+};
+int foo(struct C *c, struct B *b)
+{
+  c->a1.i = 1;
+  b->a1.i = 0;
+  return c->a1.i;
+}
+
+/* { dg-final { scan-tree-dump "return 1;" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pta-ptrarith-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pta-ptrarith-1.c
new file mode 100644 (file)
index 0000000..b61674d
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-tree-ccp -fdump-tree-alias" } */
+
+extern void abort (void);
+struct X {
+  int *p;
+  int *q;
+  int *r;
+};
+int __attribute__((noinline))
+foo(int i, int j, int k, int off)
+{
+  struct X x;
+  int **p, *q;
+  x.p = &i;
+  x.q = &j;
+  x.r = &k;
+  p = &x.q;
+  p += 1;
+  /* *p points to { k } */
+  q = *p;
+  return *q;
+}
+
+/* { dg-final { scan-tree-dump "q_., points-to vars: { k }" "alias" } } */
+/* { dg-final { cleanup-tree-dump "alias" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pta-ptrarith-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pta-ptrarith-2.c
new file mode 100644 (file)
index 0000000..adb01b2
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-tree-ccp -fdump-tree-alias" } */
+
+extern void abort (void);
+struct X {
+  int *p;
+  int *q;
+  int *r;
+};
+int __attribute__((noinline))
+foo(int i, int j, int k, int off)
+{
+  struct X x;
+  int **p, *q;
+  x.p = &i;
+  x.q = &j;
+  x.r = &k;
+  p = &x.q;
+  p -= 1;
+  /* *p points to { i } */
+  q = *p;
+  return *q;
+}
+
+/* { dg-final { scan-tree-dump "q_., points-to vars: { i }" "alias" } } */
+/* { dg-final { cleanup-tree-dump "alias" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dce-4.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dce-4.c
new file mode 100644 (file)
index 0000000..89118a6
--- /dev/null
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-cddce1" } */
+
+int foo(int b)
+{
+  int a[128];
+  a[b] = 1;
+  if (b)
+    {
+      b = 2;
+      a[2] = 0;
+    }
+  a[2] = 3;
+  return a[2] + b;
+}
+
+/* { dg-final { scan-tree-dump-times "a\\\[\[^\n\]\\\]" 2 "cddce1" } } */
+/* { dg-final { cleanup-tree-dump "cddce1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dce-5.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dce-5.c
new file mode 100644 (file)
index 0000000..11c9e66
--- /dev/null
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fno-tree-sra -fdump-tree-cddce1" } */
+
+struct X { int i; };
+struct X foo(int b)
+{
+  struct X x;
+  if (b)
+    x.i = 0;
+  x.i = 1;
+  return x;
+}
+
+/* { dg-final { scan-tree-dump-times "x.i =" 1 "cddce1" } } */
+/* { dg-final { cleanup-tree-dump "cddce1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-12.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-12.c
new file mode 100644 (file)
index 0000000..dd8f69c
--- /dev/null
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-dse1" } */
+
+void foo (int *p, int b)
+{
+  if (b)
+    *p = 1;
+  *p = 0;
+}
+
+/* { dg-final { scan-tree-dump-times "\\\*p" 1 "dse1" } } */
+/* { dg-final { cleanup-tree-dump "dse1" } } */
index a27f2d6..34217a0 100644 (file)
@@ -18,5 +18,9 @@ void __frame_state_for (volatile char *state_in, int x)
     }
 }
 
-/* { dg-final { scan-tree-dump "Insertions: 2" "pre" } } */
+/* This is a weird testcase.  It should need PPRE to hoist the loop
+   invariants and the volatileness of state_in prevents DSE of the
+   first store.  Thus, this is XFAILed.  */
+
+/* { dg-final { scan-tree-dump "Insertions: 2" "pre" { xfail *-*-* } } } */
 /* { dg-final { cleanup-tree-dump "pre" } } */
index 3253afe..ae9eb5a 100644 (file)
@@ -1,9 +1,7 @@
 /* { dg-do compile } */
-/* { dg-options "-O -fstrict-aliasing -fno-tree-sra --param max-aliased-vops=0 --param max-fields-for-field-sensitive=0 -fdump-tree-fre-details" } */
+/* { dg-options "-O -fstrict-aliasing -fno-tree-sra -fdump-tree-fre-details" } */
 
-/* Should be optimized, propagating &a into (*p)[i] with parameters
-     --param max-aliased-vops=0 --param max-fields-for-field-sensitive=0
-   which means max 1 VOP per stmt and no SFTs.  */
+/* Should be optimized, propagating &a into (*p)[i].  */
 
 /* For this testcase we need TBAA to work.  */
 
index d2d5e01..24b58ee 100644 (file)
@@ -1,9 +1,7 @@
 /* { dg-do compile } */
-/* { dg-options "-O -fno-tree-sra --param max-aliased-vops=0 --param max-fields-for-field-sensitive=0 -fdump-tree-fre-details" } */
+/* { dg-options "-O -fno-tree-sra -fdump-tree-fre-details" } */
 
-/* Should be optimized, propagating &a into (*p)[i] with parameters
-     --param max-aliased-vops=0 --param max-fields-for-field-sensitive=0
-   which means max 1 VOP per stmt and no SFTs.  */
+/* Should be optimized, propagating &a into (*p)[i].  */
 
 struct Foo
 {
index 1a286f1..a557f27 100644 (file)
@@ -1,9 +1,7 @@
 /* { dg-do compile } */
-/* { dg-options "-O -fno-tree-sra --param max-aliased-vops=0 --param max-fields-for-field-sensitive=0 -fdump-tree-fre-details" } */
+/* { dg-options "-O -fno-tree-sra -fdump-tree-fre-details" } */
 
-/* Should be optimized, propagating &a into (*p)[i] with parameters
-     --param max-aliased-vops=0 --param max-fields-for-field-sensitive=0
-   which means max 1 VOP per stmt and no SFTs.  */
+/* Should be optimized, propagating &a into (*p)[i].  */
 
 struct Foo
 {
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-18.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-18.c
new file mode 100644 (file)
index 0000000..392b1f6
--- /dev/null
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-fre" } */
+
+struct a
+{
+  union
+  {
+    int a;
+    int b;
+  };
+  union
+  {
+    int c;
+    int d;
+  };
+};
+
+int f(struct a *c)
+{
+  int d = c->a;
+  c->c = 1;
+  return c->a + d;
+}
+
+/* We should have CSEd the load from c->a.  */
+
+/* { dg-final { scan-tree-dump-times "c_.*\\\.a" 1 "fre" } } */
+/* { dg-final { cleanup-tree-dump "fre" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-19.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-19.c
new file mode 100644 (file)
index 0000000..688fe86
--- /dev/null
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-fre" } */
+
+struct a
+{
+  union
+  {
+    int a;
+    int b;
+  };
+  union
+  {
+    int c;
+    int d;
+  };
+  int e;
+};
+
+int f(struct a *c)
+{
+  int d;
+  c->e = 2;
+  d = c->a;
+  c->c = 1;
+  return c->a + d;
+}
+
+/* We should have CSEd the load from c->a.  */
+
+/* { dg-final { scan-tree-dump-times "c_.*\\\.a" 1 "fre" } } */
+/* { dg-final { cleanup-tree-dump "fre" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-20.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-20.c
new file mode 100644 (file)
index 0000000..f73ad36
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-optimized" } */
+
+int i, j;
+int foo(int b)
+{
+  j = 0;
+  if (b)
+    goto L2;
+L1:
+  i = i + 1;
+L2:
+  i = i + 1;
+  if (i == 1)
+    goto L1;
+  return j;
+}
+
+/* { dg-final { scan-tree-dump "return 0;" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
index b88a1e5..9195601 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-lim-details" } */
+/* { dg-options "-O -fdump-tree-lim-details" } */
 
 struct { int x; int y; } global;
 void foo(int n)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-23.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-23.c
new file mode 100644 (file)
index 0000000..88c8bb7
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-pre-stats" } */
+
+struct { int x; int y; } global;
+void foo(int n)
+{
+  int i;
+  for ( i=0; i<n; i++)
+    global.y += global.x*global.x;
+}
+
+/* { dg-final { scan-tree-dump "Eliminated: 2" "pre" } } */
+/* { dg-final { cleanup-tree-dump "pre" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-24.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-24.c
new file mode 100644 (file)
index 0000000..6729e2a
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-pre" } */
+
+void foo(int *p, double *x, int n)
+{
+  int i;
+  for (i = 0; i < n; ++i)
+    *(x + *p * i) = 0.0;
+}
+
+/* We should remove the unnecessary insertion of a phi-node and
+   _not_ end up using the phi result for replacement *p.
+   The issue here is that when PHI-translating the virtual operands
+   we assign different value-numbers to the load.  Re-running VN
+   after insertion or trying to be clever and doing this on the
+   fly during PHI translation would solve this.  The next copyprop
+   fixes this anyway.  */
+
+/* { dg-final { scan-tree-dump-not "= prephitmp" "pre" { xfail *-*-* } } } */
+/* { dg-final { cleanup-tree-dump "pre" } } */
index adb1461..f03dd70 100644 (file)
@@ -9,7 +9,7 @@ void
 baz (void)
 {
   int i;
-  if (i) /* { dg-warning "is used uninitialized" "uninit i warning" } */
+  if (i) /* { dg-warning "is used uninitialized" "uninit i warning" { xfail *-*-* } } */
     bar (i);
   foo (&i);
 }
index ecf9c00..53810c5 100644 (file)
@@ -29,7 +29,7 @@ void frob(int *pi);
 int main(void)
 {
   int i; 
-  printf("i = %d\n", i); /* { dg-warning "'i' is used uninitialized in this function" } */
+  printf("i = %d\n", i); /* { dg-warning "'i' is used uninitialized in this function" "" { xfail *-*-* } } */
   frob(&i);
 
   return 0;
@@ -38,6 +38,6 @@ int main(void)
 void foo3(int*);
 void bar3(void) { 
   int x; 
-  if(x) /* { dg-warning "'x' is used uninitialized in this function" "uninitialized" } */
+  if(x) /* { dg-warning "'x' is used uninitialized in this function" "uninitialized" { xfail *-*-* } } */
     foo3(&x); 
 }
index b64427f..d9bb114 100644 (file)
@@ -28,7 +28,8 @@ main1 (float *pa)
   float pb[N] __attribute__ ((__aligned__(16))) = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57};
   float pc[N] __attribute__ ((__aligned__(16))) = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
 
- /* Not vectorizable: pa may alias pb and/or pc, since their addresses escape.  */
+  /* Vectorizable: pa may not alias pb and/or pc, even though their
+     addresses escape.  &pa would need to escape to point to escaped memory.  */
   for (i = 0; i < N; i++)
     {
       pa[i] = pb[i] * pc[i];
@@ -74,6 +75,6 @@ int main (void)
   return 0;
 }
 
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" } } */
 /*  { dg-final { scan-tree-dump-times "Alignment of access forced using versioning" 1 "vect" { target vect_no_align } } } */
 /* { dg-final { cleanup-tree-dump "vect" } } */
index c27ee16..30149cd 100644 (file)
@@ -69,6 +69,7 @@ DEFTIMEVAR (TV_DF_NOTE                     , "df reg dead/unused notes")
 DEFTIMEVAR (TV_REG_STATS            , "register information")
 
 DEFTIMEVAR (TV_ALIAS_ANALYSIS       , "alias analysis")
+DEFTIMEVAR (TV_ALIAS_STMT_WALK      , "alias stmt walking")
 DEFTIMEVAR (TV_REG_SCAN                     , "register scan")
 DEFTIMEVAR (TV_REBUILD_JUMP         , "rebuild jump labels")
 /* Timing in various stages of the compiler.  */
@@ -87,11 +88,6 @@ DEFTIMEVAR (TV_TREE_COPY_PROP        , "tree copy propagation")
 DEFTIMEVAR (TV_TREE_STORE_COPY_PROP  , "tree store copy prop")
 DEFTIMEVAR (TV_FIND_REFERENCED_VARS  , "tree find ref. vars")
 DEFTIMEVAR (TV_TREE_PTA                     , "tree PTA")
-DEFTIMEVAR (TV_TREE_MAY_ALIAS        , "tree alias analysis")
-DEFTIMEVAR (TV_CALL_CLOBBER          , "tree call clobbering")
-DEFTIMEVAR (TV_FLOW_SENSITIVE        , "tree flow sensitive alias")
-DEFTIMEVAR (TV_FLOW_INSENSITIVE      , "tree flow insensitive alias")
-DEFTIMEVAR (TV_MEMORY_PARTITIONING   , "tree memory partitioning")
 DEFTIMEVAR (TV_TREE_INSERT_PHI_NODES , "tree PHI insertion")
 DEFTIMEVAR (TV_TREE_SSA_REWRITE_BLOCKS, "tree SSA rewrite")
 DEFTIMEVAR (TV_TREE_SSA_OTHER       , "tree SSA other")
index 72f3d30..fe4768d 100644 (file)
@@ -84,6 +84,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-mudflap.h"
 #include "tree-pass.h"
 #include "gimple.h"
+#include "tree-ssa-alias.h"
 
 #if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO)
 #include "dwarf2out.h"
@@ -2170,6 +2171,8 @@ dump_memory_report (bool final)
   dump_bitmap_statistics ();
   dump_vec_loc_statistics ();
   dump_ggc_loc_statistics (final);
+  dump_alias_stats (stderr);
+  dump_pta_stats (stderr);
 }
 
 /* Clean up: close opened files, etc.  */
index 301fe25..698ec2f 100644 (file)
@@ -906,6 +906,9 @@ tree_call_cdce (void)
     {
       free_dominance_info (CDI_DOMINATORS);
       free_dominance_info (CDI_POST_DOMINATORS);
+      /* As we introduced new control-flow we need to insert PHI-nodes
+         for the call-clobbers of the remaining call.  */
+      mark_sym_for_renaming (gimple_vop (cfun));
       return (TODO_update_ssa | TODO_cleanup_cfg | TODO_ggc_collect 
               | TODO_remove_unused_locals);
     }
index 66f1218..07a46df 100644 (file)
@@ -2879,7 +2879,9 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
             x = TREE_OPERAND (x, 0))
          ;
 
-       if (TREE_CODE (x) != VAR_DECL && TREE_CODE (x) != PARM_DECL)
+       if (!(TREE_CODE (x) == VAR_DECL
+             || TREE_CODE (x) == PARM_DECL
+             || TREE_CODE (x) == RESULT_DECL))
          return NULL;
        if (!TREE_ADDRESSABLE (x))
          {
@@ -4969,7 +4971,6 @@ gimple_duplicate_bb (basic_block bb)
         operands.  */
       copy = gimple_copy (stmt);
       gsi_insert_after (&gsi_tgt, copy, GSI_NEW_STMT);
-      copy_virtual_operands (copy, stmt);
       region = lookup_stmt_eh_region (stmt);
       if (region >= 0)
        add_stmt_to_eh_region (copy, region);
@@ -5141,7 +5142,7 @@ gimple_duplicate_sese_region (edge entry, edge exit,
       free_region_copy = true;
     }
 
-  gcc_assert (!need_ssa_update_p ());
+  gcc_assert (!need_ssa_update_p (cfun));
 
   /* Record blocks outside the region that are dominated by something
      inside.  */
@@ -5300,7 +5301,7 @@ gimple_duplicate_sese_tail (edge entry ATTRIBUTE_UNUSED, edge exit ATTRIBUTE_UNU
       free_region_copy = true;
     }
 
-  gcc_assert (!need_ssa_update_p ());
+  gcc_assert (!need_ssa_update_p (cfun));
 
   /* Record blocks outside the region that are dominated by something
      inside.  */
@@ -5627,19 +5628,6 @@ mark_virtual_ops_in_bb (basic_block bb)
     mark_virtual_ops_for_renaming (gsi_stmt (gsi));
 }
 
-/* Marks virtual operands of all statements in basic blocks BBS for
-   renaming.  */
-
-static void
-mark_virtual_ops_in_region (VEC (basic_block,heap) *bbs)
-{
-  basic_block bb;
-  unsigned i;
-
-  for (i = 0; VEC_iterate (basic_block, bbs, i, bb); i++)
-    mark_virtual_ops_in_bb (bb);
-}
-
 /* Move basic block BB from function CFUN to function DEST_FN.  The
    block is moved out of the original linked list and placed after
    block AFTER in the new list.  Also, the block is removed from the
@@ -5746,7 +5734,7 @@ move_block_to_fn (struct function *dest_cfun, basic_block bb,
          old_len = VEC_length (basic_block, cfg->x_label_to_block_map);
          if (old_len <= (unsigned) uid)
            {
-             new_len = 3 * uid / 2;
+             new_len = 3 * uid / 2 + 1;
              VEC_safe_grow_cleared (basic_block, gc,
                                     cfg->x_label_to_block_map, new_len);
            }
@@ -6008,11 +5996,6 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb,
 
   pop_cfun ();
 
-  /* The ssa form for virtual operands in the source function will have to
-     be repaired.  We do not care for the real operands -- the sese region
-     must be closed with respect to those.  */
-  mark_virtual_ops_in_region (bbs);
-
   /* Move blocks from BBS into DEST_CFUN.  */
   gcc_assert (VEC_length (basic_block, bbs) >= 2);
   after = dest_cfun->cfg->x_entry_block_ptr;
index 5a3cb74..ac7748e 100644 (file)
@@ -745,23 +745,6 @@ update_phi_components (basic_block bb)
     }
 }
 
-/* Mark each virtual op in STMT for ssa update.  */
-
-static void
-update_all_vops (gimple stmt)
-{
-  ssa_op_iter iter;
-  tree sym;
-
-  FOR_EACH_SSA_TREE_OPERAND (sym, stmt, iter, SSA_OP_ALL_VIRTUALS)
-    {
-      if (TREE_CODE (sym) == SSA_NAME)
-       sym = SSA_NAME_VAR (sym);
-      mark_sym_for_renaming (sym);
-    }
-}
-
-
 /* Expand a complex move to scalars.  */
 
 static void
@@ -817,7 +800,6 @@ expand_complex_move (gimple_stmt_iterator *gsi, tree type)
        }
       else
        {
-         update_all_vops (stmt);
          if (gimple_assign_rhs_code (stmt) != COMPLEX_EXPR)
            {
              r = extract_component (gsi, rhs, 0, true);
@@ -860,7 +842,6 @@ expand_complex_move (gimple_stmt_iterator *gsi, tree type)
          gimple_return_set_retval (stmt, lhs);
        }
 
-      update_all_vops (stmt);
       update_stmt (stmt);
     }
 }
index ea67f1d..305d5e4 100644 (file)
@@ -792,34 +792,15 @@ dr_analyze_indices (struct data_reference *dr, struct loop *nest)
 static void
 dr_analyze_alias (struct data_reference *dr)
 {
-  gimple stmt = DR_STMT (dr);
   tree ref = DR_REF (dr);
-  tree base = get_base_address (ref), addr, smt = NULL_TREE;
-  ssa_op_iter it;
-  tree op;
-  bitmap vops;
+  tree base = get_base_address (ref), addr;
 
-  if (DECL_P (base))
-    smt = base;
-  else if (INDIRECT_REF_P (base))
+  if (INDIRECT_REF_P (base))
     {
       addr = TREE_OPERAND (base, 0);
       if (TREE_CODE (addr) == SSA_NAME)
-       {
-         smt = symbol_mem_tag (SSA_NAME_VAR (addr));
-         DR_PTR_INFO (dr) = SSA_NAME_PTR_INFO (addr);
-       }
+       DR_PTR_INFO (dr) = SSA_NAME_PTR_INFO (addr);
     }
-
-  DR_SYMBOL_TAG (dr) = smt;
-
-  vops = BITMAP_ALLOC (NULL);
-  FOR_EACH_SSA_TREE_OPERAND (op, stmt, it, SSA_OP_VIRTUAL_USES)
-    {
-      bitmap_set_bit (vops, DECL_UID (SSA_NAME_VAR (op)));
-    }
-
-  DR_VOPS (dr) = vops;
 }
 
 /* Returns true if the address of DR is invariant.  */
@@ -842,7 +823,6 @@ dr_address_invariant_p (struct data_reference *dr)
 void
 free_data_ref (data_reference_p dr)
 {
-  BITMAP_FREE (DR_VOPS (dr));
   VEC_free (tree, heap, DR_ACCESS_FNS (dr));
   free (dr);
 }
@@ -887,8 +867,6 @@ create_data_ref (struct loop *nest, tree memref, gimple stmt, bool is_read)
       print_generic_expr (dump_file, DR_ALIGNED_TO (dr), TDF_SLIM);
       fprintf (dump_file, "\n\tbase_object: ");
       print_generic_expr (dump_file, DR_BASE_OBJECT (dr), TDF_SLIM);
-      fprintf (dump_file, "\n\tsymbol tag: ");
-      print_generic_expr (dump_file, DR_SYMBOL_TAG (dr), TDF_SLIM);
       fprintf (dump_file, "\n");
     }
 
@@ -1238,23 +1216,21 @@ dr_may_alias_p (const struct data_reference *a, const struct data_reference *b)
   const_tree type_a, type_b;
   const_tree decl_a = NULL_TREE, decl_b = NULL_TREE;
 
-  /* If the sets of virtual operands are disjoint, the memory references do not
-     alias.  */
-  if (!bitmap_intersect_p (DR_VOPS (a), DR_VOPS (b)))
-    return false;
-
   /* If the accessed objects are disjoint, the memory references do not
      alias.  */
   if (disjoint_objects_p (DR_BASE_OBJECT (a), DR_BASE_OBJECT (b)))
     return false;
 
+  /* Query the alias oracle.  */
+  if (!refs_may_alias_p (DR_REF (a), DR_REF (b)))
+    return false;
+
   if (!addr_a || !addr_b)
     return true;
 
-  /* If the references are based on different static objects, they cannot alias
-     (PTA should be able to disambiguate such accesses, but often it fails to,
-     since currently we cannot distinguish between pointer and offset in pointer
-     arithmetics).  */
+  /* If the references are based on different static objects, they cannot
+     alias (PTA should be able to disambiguate such accesses, but often
+     it fails to).  */
   if (TREE_CODE (addr_a) == ADDR_EXPR
       && TREE_CODE (addr_b) == ADDR_EXPR)
     return TREE_OPERAND (addr_a, 0) == TREE_OPERAND (addr_b, 0);
@@ -4050,7 +4026,7 @@ get_references_in_stmt (gimple stmt, VEC (data_ref_loc, heap) **references)
          && gimple_asm_volatile_p (stmt)))
     clobbers_memory = true;
 
-  if (ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
+  if (!gimple_vuse (stmt))
     return clobbers_memory;
 
   if (stmt_code == GIMPLE_ASSIGN)
@@ -4358,7 +4334,6 @@ analyze_all_data_dependences (struct loop *loop)
        {
          unsigned nb_top_relations = 0;
          unsigned nb_bot_relations = 0;
-         unsigned nb_basename_differ = 0;
          unsigned nb_chrec_relations = 0;
          struct data_dependence_relation *ddr;
 
@@ -4368,15 +4343,7 @@ analyze_all_data_dependences (struct loop *loop)
                nb_top_relations++;
          
              else if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
-               {
-                 struct data_reference *a = DDR_A (ddr);
-                 struct data_reference *b = DDR_B (ddr);
-
-                 if (!bitmap_intersect_p (DR_VOPS (a), DR_VOPS (b)))
-                   nb_basename_differ++;
-                 else
-                   nb_bot_relations++;
-               }
+               nb_bot_relations++;
          
              else 
                nb_chrec_relations++;
@@ -4939,7 +4906,7 @@ stores_from_loop (struct loop *loop, VEC (gimple, heap) **stmts)
       gimple_stmt_iterator bsi;
 
       for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
-       if (!ZERO_SSA_OPERANDS (gsi_stmt (bsi), SSA_OP_VDEF))
+       if (gimple_vdef (gsi_stmt (bsi)))
          VEC_safe_push (gimple, heap, *stmts, gsi_stmt (bsi));
     }
 
index 4a12f39..690301a 100644 (file)
@@ -88,7 +88,6 @@ struct dr_alias
 {
   /* The alias information that should be used for new pointers to this
      location.  SYMBOL_TAG is either a DECL or a SYMBOL_MEMORY_TAG.  */
-  tree symbol_tag;
   struct ptr_info_def *ptr_info;
 
   /* The set of virtual operands corresponding to this memory reference,
@@ -204,9 +203,7 @@ struct data_reference
 #define DR_OFFSET(DR)              (DR)->innermost.offset
 #define DR_INIT(DR)                (DR)->innermost.init
 #define DR_STEP(DR)                (DR)->innermost.step
-#define DR_SYMBOL_TAG(DR)          (DR)->alias.symbol_tag
 #define DR_PTR_INFO(DR)            (DR)->alias.ptr_info
-#define DR_VOPS(DR)               (DR)->alias.vops
 #define DR_ALIGNED_TO(DR)          (DR)->innermost.aligned_to
 #define DR_ACCESS_MATRIX(DR)       (DR)->access_matrix
 
index 082ac08..d50b7dd 100644 (file)
@@ -254,8 +254,9 @@ dump_referenced_vars (FILE *file)
     {
       fprintf (file, "Variable: ");
       dump_variable (file, var);
-      fprintf (file, "\n");
     }
+
+  fprintf (file, "\n");
 }
 
 
@@ -297,12 +298,6 @@ dump_variable (FILE *file, tree var)
   fprintf (file, ", ");
   print_generic_expr (file, TREE_TYPE (var), dump_flags);
 
-  if (ann && ann->symbol_mem_tag)
-    {
-      fprintf (file, ", symbol memory tag: ");
-      print_generic_expr (file, ann->symbol_mem_tag, dump_flags);
-    }
-
   if (TREE_ADDRESSABLE (var))
     fprintf (file, ", is addressable");
   
@@ -312,36 +307,10 @@ dump_variable (FILE *file, tree var)
   if (TREE_THIS_VOLATILE (var))
     fprintf (file, ", is volatile");
 
-  dump_mem_sym_stats_for_var (file, var);
-
   if (is_call_clobbered (var))
-    {
-      const char *s = "";
-      var_ann_t va = var_ann (var);
-      unsigned int escape_mask = va->escape_mask;
-
-      fprintf (file, ", call clobbered");
-      fprintf (file, " (");
-      if (escape_mask & ESCAPE_STORED_IN_GLOBAL)
-       { fprintf (file, "%sstored in global", s); s = ", "; }
-      if (escape_mask & ESCAPE_TO_ASM)
-       { fprintf (file, "%sgoes through ASM", s); s = ", "; }
-      if (escape_mask & ESCAPE_TO_CALL)
-       { fprintf (file, "%spassed to call", s); s = ", "; }
-      if (escape_mask & ESCAPE_BAD_CAST)
-       { fprintf (file, "%sbad cast", s); s = ", "; }
-      if (escape_mask & ESCAPE_TO_RETURN)
-       { fprintf (file, "%sreturned from func", s); s = ", "; }
-      if (escape_mask & ESCAPE_TO_PURE_CONST)
-       { fprintf (file, "%spassed to pure/const", s); s = ", "; }
-      if (escape_mask & ESCAPE_IS_GLOBAL)
-       { fprintf (file, "%sis global var", s); s = ", "; }
-      if (escape_mask & ESCAPE_IS_PARM)
-       { fprintf (file, "%sis incoming pointer", s); s = ", "; }
-      if (escape_mask & ESCAPE_UNKNOWN)
-       { fprintf (file, "%sunknown escape", s); s = ", "; }
-      fprintf (file, ")");
-    }
+    fprintf (file, ", call clobbered");
+  else if (is_call_used (var))
+    fprintf (file, ", call used");
 
   if (ann->noalias_state == NO_ALIAS)
     fprintf (file, ", NO_ALIAS (does not alias other NO_ALIAS symbols)");
@@ -357,27 +326,6 @@ dump_variable (FILE *file, tree var)
       print_generic_expr (file, gimple_default_def (cfun, var), dump_flags);
     }
 
-  if (MTAG_P (var) && may_aliases (var))
-    {
-      fprintf (file, ", may aliases: ");
-      dump_may_aliases_for (file, var);
-    }
-
-  if (!is_gimple_reg (var))
-    {
-      if (memory_partition (var))
-       {
-         fprintf (file, ", belongs to partition: ");
-         print_generic_expr (file, memory_partition (var), dump_flags);
-       }
-
-      if (TREE_CODE (var) == MEMORY_PARTITION_TAG)
-       {
-         fprintf (file, ", partition symbols: ");
-         dump_decl_set (file, MPT_SYMBOLS (var));
-       }
-    }
-
   fprintf (file, "\n");
 }
 
@@ -516,8 +464,8 @@ collect_dfa_stats (struct dfa_stats_d *dfa_stats_p ATTRIBUTE_UNUSED)
          gimple stmt = gsi_stmt (si);
          dfa_stats_p->num_defs += NUM_SSA_OPERANDS (stmt, SSA_OP_DEF);
          dfa_stats_p->num_uses += NUM_SSA_OPERANDS (stmt, SSA_OP_USE);
-         dfa_stats_p->num_vdefs += NUM_SSA_OPERANDS (stmt, SSA_OP_VDEF);
-         dfa_stats_p->num_vuses += NUM_SSA_OPERANDS (stmt, SSA_OP_VUSE);
+         dfa_stats_p->num_vdefs += gimple_vdef (stmt) ? 1 : 0;
+         dfa_stats_p->num_vuses += gimple_vuse (stmt) ? 1 : 0;
        }
     }
 }
@@ -650,13 +598,6 @@ add_referenced_var (tree var)
   /* Insert VAR into the referenced_vars has table if it isn't present.  */
   if (referenced_var_check_and_insert (var))
     {
-      /* This is the first time we found this variable, annotate it with
-        attributes that are intrinsic to the variable.  */
-      
-      /* Tag's don't have DECL_INITIAL.  */
-      if (MTAG_P (var))
-       return true;
-
       /* Scan DECL_INITIAL for pointer variables as they may contain
         address arithmetic referencing the address of other
         variables.  
@@ -684,22 +625,12 @@ remove_referenced_var (tree var)
   void **loc;
   unsigned int uid = DECL_UID (var);
 
-  clear_call_clobbered (var);
-  bitmap_clear_bit (gimple_call_used_vars (cfun), uid);
-  if ((v_ann = var_ann (var)))
+  /* Preserve var_anns of globals.  */
+  if (!is_global_var (var)
+      && (v_ann = var_ann (var)))
     {
-      /* Preserve var_anns of globals, but clear their alias info.  */
-      if (MTAG_P (var)
-         || (!TREE_STATIC (var) && !DECL_EXTERNAL (var)))
-       {
-         ggc_free (v_ann);
-         var->base.ann = NULL;
-       }
-      else
-       {
-         v_ann->mpt = NULL_TREE;
-         v_ann->symbol_mem_tag = NULL_TREE;
-       }
+      ggc_free (v_ann);
+      var->base.ann = NULL;
     }
   gcc_assert (DECL_P (var));
   in.uid = uid;
@@ -803,8 +734,6 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
   bool seen_variable_array_ref = false;
   bool seen_union = false;
 
-  gcc_assert (!SSA_VAR_P (exp));
-
   /* First get the final access size from just the outermost expression.  */
   if (TREE_CODE (exp) == COMPONENT_REF)
     size_tree = DECL_SIZE (TREE_OPERAND (exp, 1));
@@ -984,242 +913,3 @@ stmt_references_abnormal_ssa_name (gimple stmt)
   return false;
 }
 
-/* Return true, if the two memory references REF1 and REF2 may alias.  */
-
-bool
-refs_may_alias_p (tree ref1, tree ref2)
-{
-  tree base1, base2;
-  HOST_WIDE_INT offset1 = 0, offset2 = 0;
-  HOST_WIDE_INT size1 = -1, size2 = -1;
-  HOST_WIDE_INT max_size1 = -1, max_size2 = -1;
-  bool strict_aliasing_applies;
-
-  gcc_assert ((SSA_VAR_P (ref1)
-              || handled_component_p (ref1)
-              || INDIRECT_REF_P (ref1)
-              || TREE_CODE (ref1) == TARGET_MEM_REF)
-             && (SSA_VAR_P (ref2)
-                 || handled_component_p (ref2)
-                 || INDIRECT_REF_P (ref2)
-                 || TREE_CODE (ref2) == TARGET_MEM_REF));
-
-  /* Defer to TBAA if possible.  */
-  if (flag_strict_aliasing
-      && !alias_sets_conflict_p (get_alias_set (ref1), get_alias_set (ref2)))
-    return false;
-
-  /* Decompose the references into their base objects and the access.  */
-  base1 = ref1;
-  if (handled_component_p (ref1))
-    base1 = get_ref_base_and_extent (ref1, &offset1, &size1, &max_size1);
-  base2 = ref2;
-  if (handled_component_p (ref2))
-    base2 = get_ref_base_and_extent (ref2, &offset2, &size2, &max_size2);
-
-  /* If both references are based on different variables, they cannot alias.
-     If both references are based on the same variable, they cannot alias if
-     the accesses do not overlap.  */
-  if (SSA_VAR_P (base1)
-      && SSA_VAR_P (base2))
-    {
-      if (!operand_equal_p (base1, base2, 0))
-       return false;
-      return ranges_overlap_p (offset1, max_size1, offset2, max_size2);
-    }
-
-  /* If one base is a ref-all pointer weird things are allowed.  */
-  strict_aliasing_applies = (flag_strict_aliasing
-                            && (!INDIRECT_REF_P (base1)
-                                || get_alias_set (base1) != 0)
-                            && (!INDIRECT_REF_P (base2)
-                                || get_alias_set (base2) != 0));
-
-  /* If strict aliasing applies the only way to access a scalar variable
-     is through a pointer dereference or through a union (gcc extension).  */
-  if (strict_aliasing_applies
-      && ((SSA_VAR_P (ref2)
-          && !AGGREGATE_TYPE_P (TREE_TYPE (ref2))
-          && !INDIRECT_REF_P (ref1)
-          && TREE_CODE (TREE_TYPE (base1)) != UNION_TYPE)
-         || (SSA_VAR_P (ref1)
-             && !AGGREGATE_TYPE_P (TREE_TYPE (ref1))
-             && !INDIRECT_REF_P (ref2)
-             && TREE_CODE (TREE_TYPE (base2)) != UNION_TYPE)))
-    return false;
-
-  /* If both references are through the same type, or if strict aliasing
-     doesn't apply they are through two same pointers, they do not alias
-     if the accesses do not overlap.  */
-  if ((strict_aliasing_applies
-       && (TYPE_MAIN_VARIANT (TREE_TYPE (base1))
-          == TYPE_MAIN_VARIANT (TREE_TYPE (base2))))
-      || (TREE_CODE (base1) == INDIRECT_REF
-         && TREE_CODE (base2) == INDIRECT_REF
-         && operand_equal_p (TREE_OPERAND (base1, 0),
-                             TREE_OPERAND (base2, 0), 0)))
-    return ranges_overlap_p (offset1, max_size1, offset2, max_size2);
-
-  /* If both are component references through pointers try to find a
-     common base and apply offset based disambiguation.  This handles
-     for example
-       struct A { int i; int j; } *q;
-       struct B { struct A a; int k; } *p;
-     disambiguating q->i and p->a.j.  */
-  if (strict_aliasing_applies
-      && (TREE_CODE (base1) == INDIRECT_REF
-         || TREE_CODE (base2) == INDIRECT_REF)
-      && handled_component_p (ref1)
-      && handled_component_p (ref2))
-    {
-      tree *refp;
-      /* Now search for the type of base1 in the access path of ref2.  This
-        would be a common base for doing offset based disambiguation on.  */
-      refp = &ref2;
-      while (handled_component_p (*refp)
-            /* Note that the following is only conservative if there are
-               never copies of types appearing as sub-structures.  */
-            && (TYPE_MAIN_VARIANT (TREE_TYPE (*refp))
-                != TYPE_MAIN_VARIANT (TREE_TYPE (base1))))
-       refp = &TREE_OPERAND (*refp, 0);
-      if (TYPE_MAIN_VARIANT (TREE_TYPE (*refp))
-         == TYPE_MAIN_VARIANT (TREE_TYPE (base1)))
-       {
-         HOST_WIDE_INT offadj, sztmp, msztmp;
-         get_ref_base_and_extent (*refp, &offadj, &sztmp, &msztmp);
-         offset2 -= offadj;
-         return ranges_overlap_p (offset1, max_size1, offset2, max_size2);
-       }
-      /* The other way around.  */
-      refp = &ref1;
-      while (handled_component_p (*refp)
-            && (TYPE_MAIN_VARIANT (TREE_TYPE (*refp))
-                != TYPE_MAIN_VARIANT (TREE_TYPE (base2))))
-       refp = &TREE_OPERAND (*refp, 0);
-      if (TYPE_MAIN_VARIANT (TREE_TYPE (*refp))
-         == TYPE_MAIN_VARIANT (TREE_TYPE (base2)))
-       {
-         HOST_WIDE_INT offadj, sztmp, msztmp;
-         get_ref_base_and_extent (*refp, &offadj, &sztmp, &msztmp);
-         offset1 -= offadj;
-         return ranges_overlap_p (offset1, max_size1, offset2, max_size2);
-       }
-      /* If we can be sure to catch all equivalent types in the search
-        for the common base then we could return false here.  In that
-        case we would be able to disambiguate q->i and p->k.  */
-    }
-
-  return true;
-}
-
-/* Given a stmt STMT that references memory, return the single stmt
-   that is reached by following the VUSE -> VDEF link.  Returns
-   NULL_TREE, if there is no single stmt that defines all VUSEs of
-   STMT.
-   Note that for a stmt with a single virtual operand this may return
-   a PHI node as well.  Note that if all VUSEs are default definitions
-   this function will return an empty statement.  */
-
-gimple
-get_single_def_stmt (gimple stmt)
-{
-  gimple def_stmt = NULL;
-  tree use;
-  ssa_op_iter iter;
-
-  FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_VIRTUAL_USES)
-    {
-      gimple tmp = SSA_NAME_DEF_STMT (use);
-
-      /* ???  This is too simplistic for multiple virtual operands
-        reaching different PHI nodes of the same basic blocks or for
-        reaching all default definitions.  */
-      if (def_stmt
-         && def_stmt != tmp
-         && !(gimple_nop_p (def_stmt)
-              && gimple_nop_p (tmp)))
-       return NULL;
-
-      def_stmt = tmp;
-    }
-
-  return def_stmt;
-}
-
-/* Given a PHI node of virtual operands, tries to eliminate cyclic
-   reached definitions if they do not alias REF and returns the
-   defining statement of the single virtual operand that flows in
-   from a non-backedge.  Returns NULL_TREE if such statement within
-   the above conditions cannot be found.  */
-
-gimple
-get_single_def_stmt_from_phi (tree ref, gimple phi)
-{
-  tree def_arg = NULL_TREE;
-  unsigned i;
-
-  /* Find the single PHI argument that is not flowing in from a
-     back edge and verify that the loop-carried definitions do
-     not alias the reference we look for.  */
-  for (i = 0; i < gimple_phi_num_args (phi); ++i)
-    {
-      tree arg = PHI_ARG_DEF (phi, i);
-      gimple def_stmt;
-
-      if (!(gimple_phi_arg_edge (phi, i)->flags & EDGE_DFS_BACK))
-       {
-         /* Multiple non-back edges?  Do not try to handle this.  */
-         if (def_arg)
-           return NULL;
-         def_arg = arg;
-         continue;
-       }
-
-      /* Follow the definitions back to the original PHI node.  Bail
-        out once a definition is found that may alias REF.  */
-      def_stmt = SSA_NAME_DEF_STMT (arg);
-      do
-       {
-         if (!is_gimple_assign (def_stmt)
-             || refs_may_alias_p (ref, gimple_assign_lhs (def_stmt)))
-           return NULL;
-         /* ???  This will only work, reaching the PHI node again if
-            there is a single virtual operand on def_stmt.  */
-         def_stmt = get_single_def_stmt (def_stmt);
-         if (!def_stmt)
-           return NULL;
-       }
-      while (def_stmt != phi);
-    }
-
-  return SSA_NAME_DEF_STMT (def_arg);
-}
-
-/* Return the single reference statement defining all virtual uses
-   on STMT or NULL_TREE, if there are multiple defining statements.
-   Take into account only definitions that alias REF if following
-   back-edges when looking through a loop PHI node.  */
-
-gimple
-get_single_def_stmt_with_phi (tree ref, gimple stmt)
-{
-  switch (NUM_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_USES))
-    {
-    case 0:
-      gcc_unreachable ();
-
-    case 1:
-      {
-       gimple def_stmt = SSA_NAME_DEF_STMT (SINGLE_SSA_TREE_OPERAND
-                                            (stmt, SSA_OP_VIRTUAL_USES));
-       /* We can handle lookups over PHI nodes only for a single
-          virtual operand.  */
-       if (gimple_code (def_stmt) == GIMPLE_PHI)
-         return get_single_def_stmt_from_phi (ref, def_stmt);
-       return def_stmt;
-      }
-
-    default:
-      return get_single_def_stmt (stmt);
-    }
-}
index ffac189..c4a643e 100644 (file)
@@ -510,10 +510,6 @@ dequeue_and_dump (dump_info_p di)
     case CONST_DECL:
       dump_child ("cnst", DECL_INITIAL (t));
       break;
-      
-    case SYMBOL_MEMORY_TAG:
-    case NAME_MEMORY_TAG:
-      break;
 
     case VAR_DECL:
     case PARM_DECL:
index 59033b5..c39017b 100644 (file)
@@ -2824,8 +2824,29 @@ cleanup_empty_eh (basic_block bb)
          similar updating as jump threading does.  */
 
       for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
-       mark_sym_for_renaming (SSA_NAME_VAR (PHI_RESULT (gsi_stmt (si))));
+       {
+         tree res = PHI_RESULT (gsi_stmt (si));
+         gimple stmt;
+         imm_use_iterator iter;
+         use_operand_p use_p;
+
+         /* As we are going to delete this block we will release all
+            defs which makes the immediate uses on use stmts invalid.
+            Avoid that by replacing all uses with the bare variable
+            and updating the stmts.  */
+         FOR_EACH_IMM_USE_STMT (stmt, iter, res)
+           {
+             FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
+               SET_USE (use_p, SSA_NAME_VAR (res));
+             update_stmt (stmt);
+           }
+         mark_sym_for_renaming (SSA_NAME_VAR (res));
+       }
 
+      /* We want to thread over the current receiver to the next reachable
+         one.  Do so by deleting all outgoing EH edges from all
+        predecessors of the receiver block we are going to delete and
+        rebuild EH edges for them.  */
       while ((e = ei_safe_edge (ei_start (bb->preds))))
        {
          basic_block src = e->src;
@@ -2843,6 +2864,8 @@ cleanup_empty_eh (basic_block bb)
          if (!stmt_can_throw_internal (last_stmt (src)))
            continue;
          make_eh_edges (last_stmt (src));
+         /* Make sure to also rename symbols that feed into receivers
+            that are now newly reachable from current src.  */
          FOR_EACH_EDGE (e, ei, src->succs)
            if (e->flags & EDGE_EH)
              {
index aeba172..7de8db8 100644 (file)
@@ -35,46 +35,6 @@ gimple_in_ssa_p (const struct function *fun)
   return fun && fun->gimple_df && fun->gimple_df->in_ssa_p;
 }
 
-/* 'true' after aliases have been computed (see compute_may_aliases).  */
-static inline bool
-gimple_aliases_computed_p (const struct function *fun)
-{
-  gcc_assert (fun && fun->gimple_df);
-  return fun->gimple_df->aliases_computed_p;
-}
-
-/* Addressable variables in the function.  If bit I is set, then
-   REFERENCED_VARS (I) has had its address taken.  Note that
-   CALL_CLOBBERED_VARS and ADDRESSABLE_VARS are not related.  An
-   addressable variable is not necessarily call-clobbered (e.g., a
-   local addressable whose address does not escape) and not all
-   call-clobbered variables are addressable (e.g., a local static
-   variable).  */
-static inline bitmap
-gimple_addressable_vars (const struct function *fun)
-{
-  gcc_assert (fun && fun->gimple_df);
-  return fun->gimple_df->addressable_vars;
-}
-
-/* Call clobbered variables in the function.  If bit I is set, then
-   REFERENCED_VARS (I) is call-clobbered.  */
-static inline bitmap
-gimple_call_clobbered_vars (const struct function *fun)
-{
-  gcc_assert (fun && fun->gimple_df);
-  return fun->gimple_df->call_clobbered_vars;
-}
-
-/* Call-used variables in the function.  If bit I is set, then
-   REFERENCED_VARS (I) is call-used at pure function call-sites.  */
-static inline bitmap
-gimple_call_used_vars (const struct function *fun)
-{
-  gcc_assert (fun && fun->gimple_df);
-  return fun->gimple_df->call_used_vars;
-}
-
 /* Array of all variables referenced in the function.  */
 static inline htab_t
 gimple_referenced_vars (const struct function *fun)
@@ -84,21 +44,21 @@ gimple_referenced_vars (const struct function *fun)
   return fun->gimple_df->referenced_vars;
 }
 
-/* Artificial variable used to model the effects of function calls.  */
+/* Artificial variable used to model the effects of nonlocal
+   variables.  */
 static inline tree
-gimple_global_var (const struct function *fun)
+gimple_nonlocal_all (const struct function *fun)
 {
   gcc_assert (fun && fun->gimple_df);
-  return fun->gimple_df->global_var;
+  return fun->gimple_df->nonlocal_all;
 }
 
-/* Artificial variable used to model the effects of nonlocal
-   variables.  */
+/* Artificial variable used for the virtual operand FUD chain.  */
 static inline tree
-gimple_nonlocal_all (const struct function *fun)
+gimple_vop (const struct function *fun)
 {
   gcc_assert (fun && fun->gimple_df);
-  return fun->gimple_df->nonlocal_all;
+  return fun->gimple_df->vop;
 }
 
 /* Initialize the hashtable iterator HTI to point to hashtable TABLE */
@@ -263,14 +223,6 @@ ann_type (tree_ann_t ann)
   return ann->common.type;
 }
 
-/* Return the may_aliases bitmap for variable VAR, or NULL if it has
-   no may aliases.  */
-static inline bitmap
-may_aliases (const_tree var)
-{
-  return MTAG_ALIASES (var);
-}
-
 /* Return the line number for EXPR, or return -1 if we have no line
    number information for it.  */
 static inline int
@@ -592,17 +544,27 @@ set_is_used (tree var)
 }
 
 
-/* Return true if T (assumed to be a DECL) is a global variable.  */
+/* Return true if T (assumed to be a DECL) is a global variable.
+   A variable is considered global if its storage is not automatic.  */
 
 static inline bool
 is_global_var (const_tree t)
 {
-  if (MTAG_P (t))
-    return MTAG_GLOBAL (t);
-  else
-    return (TREE_STATIC (t) || DECL_EXTERNAL (t));
+  return (TREE_STATIC (t) || DECL_EXTERNAL (t));
+}
+
+
+/* Return true if VAR may be aliased.  A variable is considered as
+   maybe aliased if it has its address taken by the local TU
+   or possibly by another TU.  */
+
+static inline bool
+may_be_aliased (const_tree var)
+{
+  return (TREE_PUBLIC (var) || DECL_EXTERNAL (var) || TREE_ADDRESSABLE (var));
 }
 
+
 /* PHI nodes should contain only ssa_names and invariants.  A test
    for ssa_name is definitely simpler; don't let invalid contents
    slip in in the meantime.  */
@@ -632,77 +594,22 @@ loop_containing_stmt (gimple stmt)
 }
 
 
-/* Return the memory partition tag associated with symbol SYM.  */
-
-static inline tree
-memory_partition (tree sym)
-{
-  tree tag;
-
-  /* MPTs belong to their own partition.  */
-  if (TREE_CODE (sym) == MEMORY_PARTITION_TAG)
-    return sym;
-
-  gcc_assert (!is_gimple_reg (sym));
-  /* Autoparallelization moves statements from the original function (which has
-     aliases computed) to the new one (which does not).  When rebuilding
-     operands for the statement in the new function, we do not want to
-     record the memory partition tags of the original function.  */
-  if (!gimple_aliases_computed_p (cfun))
-    return NULL_TREE;
-  tag = get_var_ann (sym)->mpt;
-
-#if defined ENABLE_CHECKING
-  if (tag)
-    gcc_assert (TREE_CODE (tag) == MEMORY_PARTITION_TAG);
-#endif
-
-  return tag;
-}
-
-/* Return true if NAME is a memory factoring SSA name (i.e., an SSA
-   name for a memory partition.  */
-
+/* Return true if VAR is clobbered by function calls.  */
 static inline bool
-factoring_name_p (const_tree name)
+is_call_clobbered (const_tree var)
 {
-  return TREE_CODE (SSA_NAME_VAR (name)) == MEMORY_PARTITION_TAG;
+  return (is_global_var (var)
+         || (may_be_aliased (var)
+             && pt_solution_includes (&cfun->gimple_df->escaped, var)));
 }
 
 /* Return true if VAR is used by function calls.  */
 static inline bool
 is_call_used (const_tree var)
 {
-  return (var_ann (var)->call_clobbered
-         || bitmap_bit_p (gimple_call_used_vars (cfun), DECL_UID (var)));
-}
-
-/* Return true if VAR is clobbered by function calls.  */
-static inline bool
-is_call_clobbered (const_tree var)
-{
-  return var_ann (var)->call_clobbered;
-}
-
-/* Mark variable VAR as being clobbered by function calls.  */
-static inline void
-mark_call_clobbered (tree var, unsigned int escape_type)
-{
-  var_ann (var)->escape_mask |= escape_type;
-  var_ann (var)->call_clobbered = true;
-  bitmap_set_bit (gimple_call_clobbered_vars (cfun), DECL_UID (var));
-}
-
-/* Clear the call-clobbered attribute from variable VAR.  */
-static inline void
-clear_call_clobbered (tree var)
-{
-  var_ann_t ann = var_ann (var);
-  ann->escape_mask = 0;
-  if (MTAG_P (var))
-    MTAG_GLOBAL (var) = 0;
-  var_ann (var)->call_clobbered = false;
-  bitmap_clear_bit (gimple_call_clobbered_vars (cfun), DECL_UID (var));
+  return (is_call_clobbered (var)
+         || (may_be_aliased (var)
+             && pt_solution_includes (&cfun->gimple_df->callused, var)));
 }
 
 /* Return the common annotation for T.  Return NULL if the annotation
@@ -751,26 +658,6 @@ op_iter_next_use (ssa_op_iter *ptr)
       ptr->uses = ptr->uses->next;
       return use_p;
     }
-  if (ptr->vuses)
-    {
-      use_p = VUSE_OP_PTR (ptr->vuses, ptr->vuse_index);
-      if (++(ptr->vuse_index) >= VUSE_NUM (ptr->vuses))
-        {
-         ptr->vuse_index = 0;
-         ptr->vuses = ptr->vuses->next;
-       }
-      return use_p;
-    }
-  if (ptr->mayuses)
-    {
-      use_p = VDEF_OP_PTR (ptr->mayuses, ptr->mayuse_index);
-      if (++(ptr->mayuse_index) >= VDEF_NUM (ptr->mayuses))
-        {
-         ptr->mayuse_index = 0;
-         ptr->mayuses = ptr->mayuses->next;
-       }
-      return use_p;
-    }
   if (ptr->phi_i < ptr->num_phi)
     {
       return PHI_ARG_DEF_PTR (ptr->phi_stmt, (ptr->phi_i)++);
@@ -793,12 +680,6 @@ op_iter_next_def (ssa_op_iter *ptr)
       ptr->defs = ptr->defs->next;
       return def_p;
     }
-  if (ptr->vdefs)
-    {
-      def_p = VDEF_RESULT_PTR (ptr->vdefs);
-      ptr->vdefs = ptr->vdefs->next;
-      return def_p;
-    }
   ptr->done = true;
   return NULL_DEF_OPERAND_P;
 }
@@ -817,38 +698,12 @@ op_iter_next_tree (ssa_op_iter *ptr)
       ptr->uses = ptr->uses->next;
       return val;
     }
-  if (ptr->vuses)
-    {
-      val = VUSE_OP (ptr->vuses, ptr->vuse_index);
-      if (++(ptr->vuse_index) >= VUSE_NUM (ptr->vuses))
-        {
-         ptr->vuse_index = 0;
-         ptr->vuses = ptr->vuses->next;
-       }
-      return val;
-    }
-  if (ptr->mayuses)
-    {
-      val = VDEF_OP (ptr->mayuses, ptr->mayuse_index);
-      if (++(ptr->mayuse_index) >= VDEF_NUM (ptr->mayuses))
-        {
-         ptr->mayuse_index = 0;
-         ptr->mayuses = ptr->mayuses->next;
-       }
-      return val;
-    }
   if (ptr->defs)
     {
       val = DEF_OP (ptr->defs);
       ptr->defs = ptr->defs->next;
       return val;
     }
-  if (ptr->vdefs)
-    {
-      val = VDEF_RESULT (ptr->vdefs);
-      ptr->vdefs = ptr->vdefs->next;
-      return val;
-    }
 
   ptr->done = true;
   return NULL_TREE;
@@ -865,34 +720,36 @@ clear_and_done_ssa_iter (ssa_op_iter *ptr)
 {
   ptr->defs = NULL;
   ptr->uses = NULL;
-  ptr->vuses = NULL;
-  ptr->vdefs = NULL;
-  ptr->mayuses = NULL;
   ptr->iter_type = ssa_op_iter_none;
   ptr->phi_i = 0;
   ptr->num_phi = 0;
   ptr->phi_stmt = NULL;
   ptr->done = true;
-  ptr->vuse_index = 0;
-  ptr->mayuse_index = 0;
 }
 
 /* Initialize the iterator PTR to the virtual defs in STMT.  */
 static inline void
 op_iter_init (ssa_op_iter *ptr, gimple stmt, int flags)
 {
-  ptr->defs = (flags & SSA_OP_DEF) ? gimple_def_ops (stmt) : NULL;
-  ptr->uses = (flags & SSA_OP_USE) ? gimple_use_ops (stmt) : NULL;
-  ptr->vuses = (flags & SSA_OP_VUSE) ? gimple_vuse_ops (stmt) : NULL;
-  ptr->vdefs = (flags & SSA_OP_VDEF) ? gimple_vdef_ops (stmt) : NULL;
-  ptr->mayuses = (flags & SSA_OP_VMAYUSE) ? gimple_vdef_ops (stmt) : NULL;
+  /* We do not support iterating over virtual defs or uses without
+     iterating over defs or uses at the same time.  */
+  gcc_assert ((!(flags & SSA_OP_VDEF) || (flags & SSA_OP_DEF))
+             && (!(flags & SSA_OP_VUSE) || (flags & SSA_OP_USE)));
+  ptr->defs = (flags & (SSA_OP_DEF|SSA_OP_VDEF)) ? gimple_def_ops (stmt) : NULL;
+  if (!(flags & SSA_OP_VDEF)
+      && ptr->defs
+      && gimple_vdef (stmt) != NULL_TREE)
+    ptr->defs = ptr->defs->next;
+  ptr->uses = (flags & (SSA_OP_USE|SSA_OP_VUSE)) ? gimple_use_ops (stmt) : NULL;
+  if (!(flags & SSA_OP_VUSE)
+      && ptr->uses
+      && gimple_vuse (stmt) != NULL_TREE)
+    ptr->uses = ptr->uses->next;
   ptr->done = false;
 
   ptr->phi_i = 0;
   ptr->num_phi = 0;
   ptr->phi_stmt = NULL;
-  ptr->vuse_index = 0;
-  ptr->mayuse_index = 0;
 }
 
 /* Initialize iterator PTR to the use operands in STMT based on FLAGS. Return
@@ -900,7 +757,8 @@ op_iter_init (ssa_op_iter *ptr, gimple stmt, int flags)
 static inline use_operand_p
 op_iter_init_use (ssa_op_iter *ptr, gimple stmt, int flags)
 {
-  gcc_assert ((flags & SSA_OP_ALL_DEFS) == 0);
+  gcc_assert ((flags & SSA_OP_ALL_DEFS) == 0
+             && (flags & SSA_OP_USE));
   op_iter_init (ptr, stmt, flags);
   ptr->iter_type = ssa_op_iter_use;
   return op_iter_next_use (ptr);
@@ -911,7 +769,8 @@ op_iter_init_use (ssa_op_iter *ptr, gimple stmt, int flags)
 static inline def_operand_p
 op_iter_init_def (ssa_op_iter *ptr, gimple stmt, int flags)
 {
-  gcc_assert ((flags & SSA_OP_ALL_USES) == 0);
+  gcc_assert ((flags & SSA_OP_ALL_USES) == 0
+             && (flags & SSA_OP_DEF));
   op_iter_init (ptr, stmt, flags);
   ptr->iter_type = ssa_op_iter_def;
   return op_iter_next_def (ptr);
@@ -927,58 +786,6 @@ op_iter_init_tree (ssa_op_iter *ptr, gimple stmt, int flags)
   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_vdef (vuse_vec_p *use, def_operand_p *def, 
-                        ssa_op_iter *ptr)
-{
-#ifdef ENABLE_CHECKING
-  gcc_assert (ptr->iter_type == ssa_op_iter_vdef);
-#endif
-  if (ptr->mayuses)
-    {
-      *def = VDEF_RESULT_PTR (ptr->mayuses);
-      *use = VDEF_VECT (ptr->mayuses);
-      ptr->mayuses = ptr->mayuses->next;
-      return;
-    }
-
-  *def = NULL_DEF_OPERAND_P;
-  *use = NULL;
-  ptr->done = true;
-  return;
-}
-
-
-static inline void
-op_iter_next_mustdef (use_operand_p *use, def_operand_p *def, 
-                        ssa_op_iter *ptr)
-{
-  vuse_vec_p vp;
-  op_iter_next_vdef (&vp, def, ptr);
-  if (vp != NULL)
-    {
-      gcc_assert (VUSE_VECT_NUM_ELEM (*vp) == 1);
-      *use = VUSE_ELEMENT_PTR (*vp, 0);
-    }
-  else
-    *use = NULL_USE_OPERAND_P;
-}
-
-/* Initialize iterator PTR to the operands in STMT.  Return the first operands
-   in USE and DEF.  */
-static inline void
-op_iter_init_vdef (ssa_op_iter *ptr, gimple stmt, vuse_vec_p *use, 
-                    def_operand_p *def)
-{
-  gcc_assert (gimple_code (stmt) != GIMPLE_PHI);
-
-  op_iter_init (ptr, stmt, SSA_OP_VMAYUSE);
-  ptr->iter_type = ssa_op_iter_vdef;
-  op_iter_next_vdef (use, def, ptr);
-}
-
 
 /* If there is a single operand in STMT matching FLAGS, return it.  Otherwise
    return NULL.  */
@@ -1074,52 +881,6 @@ delink_stmt_imm_use (gimple stmt)
 }
 
 
-/* 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 (gimple stmt1, gimple 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 != NULL;
-  look2 = stmt2 != NULL;
-
-  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
@@ -1177,11 +938,12 @@ op_iter_init_phidef (ssa_op_iter *ptr, gimple phi, int flags)
 
   comp = (is_gimple_reg (phi_def) ? SSA_OP_DEF : SSA_OP_VIRTUAL_DEFS);
     
-  /* If the PHI node doesn't the operand type we care about, we're done.  */
+  /* If the PHI node doesn't have the operand type we care about,
+     we're done.  */
   if ((flags & comp) == 0)
     {
       ptr->done = true;
-      return NULL_USE_OPERAND_P;
+      return NULL_DEF_OPERAND_P;
     }
 
   ptr->iter_type = ssa_op_iter_def;
@@ -1261,9 +1023,17 @@ link_use_stmts_after (use_operand_p head, imm_use_iterator *imm)
     }
   else
     {
-      FOR_EACH_SSA_USE_OPERAND (use_p, head_stmt, op_iter, flag)
-       if (USE_FROM_PTR (use_p) == use)
-         last_p = move_use_after_head (use_p, head, last_p);
+      if (flag == SSA_OP_USE)
+       {
+         FOR_EACH_SSA_USE_OPERAND (use_p, head_stmt, op_iter, flag)
+           if (USE_FROM_PTR (use_p) == use)
+             last_p = move_use_after_head (use_p, head, last_p);
+       }
+      else if ((use_p = gimple_vuse_op (head_stmt)) != NULL_USE_OPERAND_P)
+       {
+         if (USE_FROM_PTR (use_p) == use)
+           last_p = move_use_after_head (use_p, head, last_p);
+       }
     }
   /* Link iter node in after last_p.  */
   if (imm->iter_node.prev != NULL)
@@ -1287,7 +1057,7 @@ first_imm_use_stmt (imm_use_iterator *imm, tree var)
   imm->iter_node.prev = NULL_USE_OPERAND_P;
   imm->iter_node.next = NULL_USE_OPERAND_P;
   imm->iter_node.loc.stmt = NULL;
-  imm->iter_node.use = NULL_USE_OPERAND_P;
+  imm->iter_node.use = NULL;
 
   if (end_imm_use_stmt_p (imm))
     return NULL;
@@ -1355,9 +1125,6 @@ unmodifiable_var_p (const_tree var)
   if (TREE_CODE (var) == SSA_NAME)
     var = SSA_NAME_VAR (var);
 
-  if (MTAG_P (var))
-    return false;
-
   return TREE_READONLY (var) && (TREE_STATIC (var) || DECL_EXTERNAL (var));
 }
 
@@ -1414,35 +1181,6 @@ ranges_overlap_p (unsigned HOST_WIDE_INT pos1,
   return false;
 }
 
-/* Return the memory tag associated with symbol SYM.  */
-
-static inline tree
-symbol_mem_tag (tree sym)
-{
-  tree tag = get_var_ann (sym)->symbol_mem_tag;
-
-#if defined ENABLE_CHECKING
-  if (tag)
-    gcc_assert (TREE_CODE (tag) == SYMBOL_MEMORY_TAG);
-#endif
-
-  return tag;
-}
-
-
-/* Set the memory tag associated with symbol SYM.  */
-
-static inline void
-set_symbol_mem_tag (tree sym, tree tag)
-{
-#if defined ENABLE_CHECKING
-  if (tag)
-    gcc_assert (TREE_CODE (tag) == SYMBOL_MEMORY_TAG);
-#endif
-
-  get_var_ann (sym)->symbol_mem_tag = tag;
-}
-
 /* Accessor to tree-ssa-operands.c caches.  */
 static inline struct ssa_operands *
 gimple_ssa_operands (const struct function *fun)
@@ -1450,13 +1188,6 @@ gimple_ssa_operands (const struct function *fun)
   return &fun->gimple_df->ssa_operands;
 }
 
-/* Map describing reference statistics for function FN.  */
-static inline struct mem_ref_stats_d *
-gimple_mem_ref_stats (const struct function *fn)
-{
-  return &fn->gimple_df->mem_ref_stats;
-}
-
 /* Given an edge_var_map V, return the PHI arg definition.  */
 
 static inline tree
index 868b762..f2d7c5f 100644 (file)
@@ -30,6 +30,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-ssa-operands.h"
 #include "cgraph.h"
 #include "ipa-reference.h"
+#include "tree-ssa-alias.h"
 
 /* Forward declare structures for the garbage collector GTY markers.  */
 #ifndef GCC_BASIC_BLOCK_H
@@ -40,98 +41,6 @@ typedef struct basic_block_def *basic_block;
 #endif
 struct static_var_ann_d;
 
-/* The reasons a variable may escape a function.  */
-enum escape_type 
-{
-  NO_ESCAPE = 0,                       /* Doesn't escape.  */
-  ESCAPE_STORED_IN_GLOBAL = 1 << 0,
-  ESCAPE_TO_ASM = 1 << 1,              /* Passed by address to an assembly
-                                          statement.  */
-  ESCAPE_TO_CALL = 1 << 2,             /* Escapes to a function call.  */
-  ESCAPE_BAD_CAST = 1 << 3,            /* Cast from pointer to integer */
-  ESCAPE_TO_RETURN = 1 << 4,           /* Returned from function.  */
-  ESCAPE_TO_PURE_CONST = 1 << 5,       /* Escapes to a pure or constant
-                                          function call.  */
-  ESCAPE_IS_GLOBAL = 1 << 6,           /* Is a global variable.  */
-  ESCAPE_IS_PARM = 1 << 7,             /* Is an incoming function argument.  */
-  ESCAPE_UNKNOWN = 1 << 8              /* We believe it escapes for
-                                          some reason not enumerated
-                                          above.  */
-};
-
-/* Memory reference statistics for individual memory symbols,
-   collected during alias analysis.  */
-struct mem_sym_stats_d GTY(())
-{
-  /* Memory symbol.  */
-  tree var;
-
-  /* Nonzero if this entry has been assigned a partition.  */
-  unsigned int partitioned_p : 1;
-
-  /* Nonzero if VAR is a memory partition tag that already contains
-     call-clobbered variables in its partition set.  */
-  unsigned int has_call_clobbered_vars : 1;
-
-  /* Number of direct reference sites.  A direct reference to VAR is any
-     reference of the form 'VAR = ' or ' = VAR'.  For GIMPLE reg
-     pointers, this is the number of sites where the pointer is
-     dereferenced.  */
-  long num_direct_writes;
-  long num_direct_reads;
-
-  /* Number of indirect reference sites.  An indirect reference to VAR
-     is any reference via a pointer that contains VAR in its points-to
-     set or, in the case of call-clobbered symbols, a function call.  */
-  long num_indirect_writes;
-  long num_indirect_reads;
-
-  /* Execution frequency.  This is the sum of the execution
-     frequencies of all the statements that reference this object
-     weighted by the number of references in each statement.  This is
-     the main key used to sort the list of symbols to partition.
-     Symbols with high execution frequencies are put at the bottom of
-     the work list (ie, they are partitioned last).
-     Execution frequencies are taken directly from each basic block,
-     so compiling with PGO enabled will increase the precision of this
-     estimate.  */
-  long frequency_reads;
-  long frequency_writes;
-
-  /* Set of memory tags that contain VAR in their alias set.  */
-  bitmap parent_tags;
-};
-
-typedef struct mem_sym_stats_d *mem_sym_stats_t;
-DEF_VEC_P(mem_sym_stats_t);
-DEF_VEC_ALLOC_P(mem_sym_stats_t, heap);
-
-/* Memory reference statistics collected during alias analysis.  */
-struct mem_ref_stats_d GTY(())
-{
-  /* Number of statements that make memory references.  */
-  long num_mem_stmts;
-
-  /* Number of statements that make function calls.  */
-  long num_call_sites;
-
-  /* Number of statements that make calls to pure/const functions.  */
-  long num_pure_const_call_sites;
-
-  /* Number of ASM statements.  */
-  long num_asm_sites;
-
-  /* Estimated number of virtual operands needed as computed by
-   compute_memory_partitions.  */
-  long num_vuses;
-  long num_vdefs;
-
-  /* This maps every symbol used to make "memory" references
-     (pointers, arrays, structures, etc) to an instance of struct
-     mem_sym_stats_d describing reference statistics for the symbol.  */
-  struct pointer_map_t * GTY((skip)) mem_sym_stats;
-};
-
 
 /* Gimple dataflow datastructure. All publicly available fields shall have
    gimple_ accessor defined in tree-flow-inline.h, all publicly modifiable
@@ -151,29 +60,18 @@ struct gimple_df GTY(())
   /* Array of all SSA_NAMEs used in the function.  */
   VEC(tree,gc) *ssa_names;
 
-  /* Artificial variable used to model the effects of function calls.  */
-  tree global_var;
+  /* Artificial variable used for the virtual operand FUD chain.  */
+  tree vop;
 
   /* Artificial variable used to model the effects of nonlocal
      variables.  */
   tree nonlocal_all;
 
-  /* Call clobbered variables in the function.  If bit I is set, then
-     REFERENCED_VARS (I) is call-clobbered.  */
-  bitmap call_clobbered_vars;
-
-  /* Call-used variables in the function.  If bit I is set, then
-     REFERENCED_VARS (I) is call-used at pure function call-sites.  */
-  bitmap call_used_vars;
+  /* The PTA solution for the ESCAPED artificial variable.  */
+  struct pt_solution escaped;
 
-  /* Addressable variables in the function.  If bit I is set, then
-     REFERENCED_VARS (I) has had its address taken.  Note that
-     CALL_CLOBBERED_VARS and ADDRESSABLE_VARS are not related.  An
-     addressable variable is not necessarily call-clobbered (e.g., a
-     local addressable whose address does not escape) and not all
-     call-clobbered variables are addressable (e.g., a local static
-     variable).  */
-  bitmap addressable_vars;
+  /* The PTA solution for the CALLUSED artificial variable.  */
+  struct pt_solution callused;
 
   /* Free list of SSA_NAMEs.  */
   tree free_ssanames;
@@ -184,18 +82,14 @@ struct gimple_df GTY(())
      for this variable with an empty defining statement.  */
   htab_t GTY((param_is (union tree_node))) default_defs;
 
-  /* 'true' after aliases have been computed (see compute_may_aliases).  */
-  unsigned int aliases_computed_p : 1;
+  /* Symbols whose SSA form needs to be updated or created for the first
+     time.  */
+  bitmap syms_to_rename;
 
   /* True if the code is in ssa form.  */
   unsigned int in_ssa_p : 1;
 
   struct ssa_operands ssa_operands;
-
-  /* Memory reference statistics collected during alias analysis.
-     This information is used to drive the memory partitioning
-     heuristics in compute_memory_partitions.  */
-  struct mem_ref_stats_d mem_ref_stats;
 };
 
 /* Accessors for internal use only.  Generic code should use abstraction
@@ -204,6 +98,7 @@ struct gimple_df GTY(())
 #define SSANAMES(fun) (fun)->gimple_df->ssa_names
 #define MODIFIED_NORETURN_CALLS(fun) (fun)->gimple_df->modified_noreturn_calls
 #define DEFAULT_DEFS(fun) (fun)->gimple_df->default_defs
+#define SYMS_TO_RENAME(fun) (fun)->gimple_df->syms_to_rename
 
 typedef struct
 {
@@ -231,37 +126,8 @@ typedef struct
 /* Aliasing information for SSA_NAMEs representing pointer variables.  */
 struct ptr_info_def GTY(())
 {
-  /* Mask of reasons this pointer's value escapes the function.  */
-  ENUM_BITFIELD (escape_type) escape_mask : 9;
-
-  /* Nonzero if points-to analysis couldn't determine where this pointer
-     is pointing to.  */
-  unsigned int pt_anything : 1;
-
-  /* Nonzero if the value of this pointer escapes the current function.  */
-  unsigned int value_escapes_p : 1;
-
-  /* Nonzero if a memory tag is needed for this pointer.  This is
-     true if this pointer is eventually dereferenced.  */
-  unsigned int memory_tag_needed : 1;
-
-  /* Nonzero if this pointer is really dereferenced.  */
-  unsigned int is_dereferenced : 1;
-
-  /* Nonzero if this pointer points to a global variable.  */
-  unsigned int pt_global_mem : 1;
-
-  /* Nonzero if this pointer points to NULL.  */
-  unsigned int pt_null : 1;
-
-  /* Set of variables that this pointer may point to.  */
-  bitmap pt_vars;
-
-  /* If this pointer has been dereferenced, and points-to information is
-     more precise than type-based aliasing, indirect references to this
-     pointer will be represented by this memory tag, instead of the type
-     tag computed by TBAA.  */
-  tree name_mem_tag;
+  /* The points-to solution, TBAA-pruned if the pointer is dereferenced.  */
+  struct pt_solution pt;
 };
 
 
@@ -359,42 +225,15 @@ struct var_ann_d GTY(())
      states.  */
   ENUM_BITFIELD (need_phi_state) need_phi_state : 2;
 
-  /* Used during operand processing to determine if this variable is already 
-     in the VUSE list.  */
-  unsigned in_vuse_list : 1;
-
-  /* Used during operand processing to determine if this variable is already 
-     in the VDEF list.  */
-  unsigned in_vdef_list : 1;
-
   /* True for HEAP artificial variables.  These variables represent
      the memory area allocated by a call to malloc.  */
   unsigned is_heapvar : 1;
 
-  /* True if the variable is call clobbered.  */
-  unsigned call_clobbered : 1;
-
   /* This field describes several "no alias" attributes that some
      symbols are known to have.  See the enum's definition for more
      information on each attribute.  */
   ENUM_BITFIELD (noalias_state) noalias_state : 2;
 
-  /* Mask of values saying the reasons why this variable has escaped
-     the function.  */
-  ENUM_BITFIELD (escape_type) escape_mask : 9;
-
-  /* Memory partition tag assigned to this symbol.  */
-  tree mpt;
-
-  /* If this variable is a pointer P that has been dereferenced, this
-     field is an artificial variable that represents the memory
-     location *P.  Every other pointer Q that is type-compatible with
-     P will also have the same memory tag.  If the variable is not a
-     pointer or if it is never dereferenced, this must be NULL.
-     FIXME, do we really need this here?  How much slower would it be
-     to convert to hash table?  */
-  tree symbol_mem_tag;
-
   /* Used when going out of SSA form to indicate which partition this
      variable represents storage for.  */
   unsigned partition;
@@ -535,7 +374,6 @@ static inline function_ann_t function_ann (const_tree);
 static inline function_ann_t get_function_ann (tree);
 static inline enum tree_ann_type ann_type (tree_ann_t);
 static inline void update_stmt (gimple);
-static inline bitmap may_aliases (const_tree);
 static inline int get_lineno (const_gimple);
 
 /*---------------------------------------------------------------------------
@@ -776,10 +614,8 @@ extern tree make_rename_temp (tree, const char *);
 extern void set_default_def (tree, tree);
 extern tree gimple_default_def (struct function *, tree);
 extern bool stmt_references_abnormal_ssa_name (gimple);
-extern bool refs_may_alias_p (tree, tree);
-extern gimple get_single_def_stmt (gimple);
-extern gimple get_single_def_stmt_from_phi (tree, gimple);
-extern gimple get_single_def_stmt_with_phi (tree, gimple);
+extern tree get_ref_base_and_extent (tree, HOST_WIDE_INT *,
+                                    HOST_WIDE_INT *, HOST_WIDE_INT *);
 
 /* In tree-phinodes.c  */
 extern void reserve_phi_args_for_new_edge (basic_block);
@@ -804,43 +640,6 @@ extern bool block_may_fallthru (const_tree);
 extern bool gimple_seq_may_fallthru (gimple_seq);
 extern bool gimple_stmt_may_fallthru (gimple);
 
-/* In tree-ssa-alias.c  */
-extern unsigned int compute_may_aliases (void);
-extern void dump_may_aliases_for (FILE *, tree);
-extern void debug_may_aliases_for (tree);
-extern void dump_alias_info (FILE *);
-extern void debug_alias_info (void);
-extern void dump_points_to_info (FILE *);
-extern void debug_points_to_info (void);
-extern void dump_points_to_info_for (FILE *, tree);
-extern void debug_points_to_info_for (tree);
-extern bool may_be_aliased (tree);
-extern bool may_alias_p (tree, alias_set_type, tree, alias_set_type, bool);
-extern struct ptr_info_def *get_ptr_info (tree);
-extern bool may_point_to_global_var (tree);
-extern void new_type_alias (tree, tree, tree);
-extern void count_uses_and_derefs (tree, gimple, unsigned *, unsigned *,
-                                  unsigned *);
-static inline bool ref_contains_array_ref (const_tree);
-static inline bool array_ref_contains_indirect_ref (const_tree);
-extern tree get_ref_base_and_extent (tree, HOST_WIDE_INT *,
-                                    HOST_WIDE_INT *, HOST_WIDE_INT *);
-extern tree create_tag_raw (enum tree_code, tree, const char *);
-extern void delete_mem_ref_stats (struct function *);
-extern void dump_mem_ref_stats (FILE *);
-extern void debug_mem_ref_stats (void);
-extern void debug_memory_partitions (void);
-extern void debug_mem_sym_stats (tree var);
-extern void dump_mem_sym_stats_for_var (FILE *, tree);
-extern void debug_all_mem_sym_stats (void);
-
-/* Call-back function for walk_use_def_chains().  At each reaching
-   definition, a function with this prototype is called.  */
-typedef bool (*walk_use_def_chains_fn) (tree, gimple, void *);
-
-/* In tree-ssa-alias-warnings.c  */
-extern void strict_aliasing_warning_backend (void);
-
 
 /* In tree-ssa.c  */
 
@@ -869,8 +668,14 @@ extern edge ssa_redirect_edge (edge, basic_block);
 extern void flush_pending_stmts (edge);
 extern void verify_ssa (bool);
 extern void delete_tree_ssa (void);
-extern void walk_use_def_chains (tree, walk_use_def_chains_fn, void *, bool);
 extern bool ssa_undefined_value_p (tree);
+extern void execute_update_addresses_taken (bool);
+
+/* Call-back function for walk_use_def_chains().  At each reaching
+   definition, a function with this prototype is called.  */
+typedef bool (*walk_use_def_chains_fn) (tree, gimple, void *);
+
+extern void walk_use_def_chains (tree, walk_use_def_chains_fn, void *, bool);
 
 
 /* In tree-into-ssa.c  */
@@ -878,7 +683,7 @@ void update_ssa (unsigned);
 void delete_update_ssa (void);
 void register_new_name_mapping (tree, tree);
 tree create_new_def_for (tree, gimple, def_operand_p);
-bool need_ssa_update_p (void);
+bool need_ssa_update_p (struct function *);
 bool name_mappings_registered_p (void);
 bool name_registered_for_update_p (tree);
 bitmap ssa_names_to_replace (void);
@@ -1065,9 +870,10 @@ char *get_lsm_tmp_name (tree, unsigned);
 
 /* In tree-flow-inline.h  */
 static inline bool is_call_clobbered (const_tree);
-static inline void mark_call_clobbered (tree, unsigned int);
 static inline void set_is_used (tree);
 static inline bool unmodifiable_var_p (const_tree);
+static inline bool ref_contains_array_ref (const_tree);
+static inline bool array_ref_contains_indirect_ref (const_tree);
 
 /* In tree-eh.c  */
 extern void make_eh_edges (gimple);
@@ -1149,11 +955,6 @@ tree force_gimple_operand_gsi (gimple_stmt_iterator *, tree, bool, tree,
 tree gimple_fold_indirect_ref (tree);
 void mark_addressable (tree);
 
-/* In tree-ssa-structalias.c */
-bool find_what_p_points_to (tree);
-bool clobber_what_escaped (void);
-void compute_call_used_vars (void);
-
 /* In tree-ssa-live.c */
 extern void remove_unused_locals (void);
 extern void dump_scope_blocks (FILE *, int);
@@ -1174,8 +975,6 @@ rtx addr_for_mem_ref (struct mem_address *, bool);
 void get_address_description (tree, struct mem_address *);
 tree maybe_fold_tmr (tree);
 
-void init_alias_heapvars (void);
-void delete_alias_heapvars (void);
 unsigned int execute_fixup_cfg (void);
 
 #include "tree-flow-inline.h"
index 609a081..e1e1f11 100644 (file)
@@ -1297,6 +1297,14 @@ remap_gimple_stmt (gimple stmt, copy_body_data *id)
   else
     walk_gimple_op (copy, remap_gimple_op_r, &wi); 
 
+  /* Clear the copied virtual operands.  We are not remapping them here
+     but are going to recreate them from scratch.  */
+  if (gimple_has_mem_ops (copy))
+    {
+      gimple_set_vdef (copy, NULL_TREE);
+      gimple_set_vuse (copy, NULL_TREE);
+    }
+
   /* We have to handle EH region remapping of GIMPLE_RESX specially because
      the region number is not an operand.  */
   if (gimple_code (stmt) == GIMPLE_RESX && id->eh_region_offset)
@@ -3410,6 +3418,9 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id)
   pointer_map_destroy (id->decl_map);
   id->decl_map = st;
 
+  /* Unlink the calls virtual operands before replacing it.  */
+  unlink_stmt_vdef (stmt);
+
   /* If the inlined function returns a result that we care about,
      substitute the GIMPLE_CALL with an assignment of the return
      variable to the LHS of the call.  That is, if STMT was
@@ -3420,10 +3431,7 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id)
       stmt = gimple_build_assign (gimple_call_lhs (stmt), use_retvar);
       gsi_replace (&stmt_gsi, stmt, false);
       if (gimple_in_ssa_p (cfun))
-       {
-          update_stmt (stmt);
-          mark_symbols_for_renaming (stmt);
-       }
+       mark_symbols_for_renaming (stmt);
       maybe_clean_or_replace_eh_stmt (old_stmt, stmt);
     }
   else
@@ -3443,7 +3451,6 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id)
                 undefined via a move.  */
              stmt = gimple_build_assign (gimple_call_lhs (stmt), def);
              gsi_replace (&stmt_gsi, stmt, true);
-             update_stmt (stmt);
            }
          else
            {
@@ -4451,28 +4458,16 @@ tree_function_versioning (tree old_decl, tree new_decl, varray_type tree_map,
 
   /* Clean up.  */
   pointer_map_destroy (id.decl_map);
+  free_dominance_info (CDI_DOMINATORS);
+  free_dominance_info (CDI_POST_DOMINATORS);
   if (!update_clones)
     {
       fold_marked_statements (0, id.statements_to_fold);
       pointer_set_destroy (id.statements_to_fold);
       fold_cond_expr_cond ();
-    }
-  if (gimple_in_ssa_p (cfun))
-    {
-      free_dominance_info (CDI_DOMINATORS);
-      free_dominance_info (CDI_POST_DOMINATORS);
-      if (!update_clones)
-        delete_unreachable_blocks ();
+      delete_unreachable_blocks ();
       update_ssa (TODO_update_ssa);
-      if (!update_clones)
-       {
-         fold_cond_expr_cond ();
-         if (need_ssa_update_p ())
-           update_ssa (TODO_update_ssa);
-       }
     }
-  free_dominance_info (CDI_DOMINATORS);
-  free_dominance_info (CDI_POST_DOMINATORS);
   VEC_free (gimple, heap, init_stmts);
   pop_cfun ();
   current_function_decl = old_current_function_decl;
index 928333b..67f8fd8 100644 (file)
@@ -113,10 +113,6 @@ static sbitmap old_ssa_names;
 static sbitmap new_ssa_names;
 
 
-/* Symbols whose SSA form needs to be updated or created for the first
-   time.  */
-static bitmap syms_to_rename;
-
 /* Subset of SYMS_TO_RENAME.  Contains all the GIMPLE register symbols
    that have been marked for renaming.  */
 static bitmap regs_to_rename;
@@ -155,12 +151,9 @@ struct repl_map_d
    then REPL_TBL[N_i] = { O_1, O_2, ..., O_j }.  */
 static htab_t repl_tbl;
 
-/* true if register_new_name_mapping needs to initialize the data
-   structures needed by update_ssa.  */
-static bool need_to_initialize_update_ssa_p = true;
-
-/* true if update_ssa needs to update virtual operands.  */
-static bool need_to_update_vops_p = false;
+/* The function the SSA updating data structures have been initialized for.
+   NULL if they need to be initialized by register_new_name_mapping.  */
+static struct function *update_ssa_initialized_fn = NULL;
 
 /* Statistics kept by update_ssa to use in the virtual mapping
    heuristic.  If the number of virtual mappings is beyond certain
@@ -585,7 +578,7 @@ set_livein_block (tree var, basic_block bb)
 static inline bool
 symbol_marked_for_renaming (tree sym)
 {
-  return bitmap_bit_p (syms_to_rename, DECL_UID (sym));
+  return bitmap_bit_p (SYMS_TO_RENAME (cfun), DECL_UID (sym));
 }
 
 
@@ -595,6 +588,8 @@ static inline bool
 is_old_name (tree name)
 {
   unsigned ver = SSA_NAME_VERSION (name);
+  if (!new_ssa_names)
+    return false;
   return ver < new_ssa_names->n_bits && TEST_BIT (old_ssa_names, ver);
 }
 
@@ -605,6 +600,8 @@ static inline bool
 is_new_name (tree name)
 {
   unsigned ver = SSA_NAME_VERSION (name);
+  if (!new_ssa_names)
+    return false;
   return ver < new_ssa_names->n_bits && TEST_BIT (new_ssa_names, ver);
 }
 
@@ -695,8 +692,6 @@ add_new_name_mapping (tree new_tree, tree old)
     {
       tree sym;
 
-      need_to_update_vops_p = true;
-
       update_ssa_stats.num_virtual_mappings++;
       update_ssa_stats.num_virtual_symbols++;
 
@@ -1455,10 +1450,10 @@ dump_decl_set (FILE *file, bitmap set)
          fprintf (file, " ");
        }
 
-      fprintf (file, "}\n");
+      fprintf (file, "}");
     }
   else
-    fprintf (file, "NIL\n");
+    fprintf (file, "NIL");
 }
 
 
@@ -1468,6 +1463,7 @@ void
 debug_decl_set (bitmap set)
 {
   dump_decl_set (stderr, set);
+  fprintf (stderr, "\n");
 }
 
 
@@ -1551,7 +1547,8 @@ dump_currdefs (FILE *file)
 
   fprintf (file, "\n\nCurrent reaching definitions\n\n");
   FOR_EACH_REFERENCED_VAR (var, i)
-    if (syms_to_rename == NULL || bitmap_bit_p (syms_to_rename, DECL_UID (var)))
+    if (SYMS_TO_RENAME (cfun) == NULL
+       || bitmap_bit_p (SYMS_TO_RENAME (cfun), DECL_UID (var)))
       {
        fprintf (file, "CURRDEF (");
        print_generic_expr (file, var, 0);
@@ -1943,27 +1940,15 @@ rewrite_update_stmt (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
   /* Rewrite USES included in OLD_SSA_NAMES and USES whose underlying
      symbol is marked for renaming.  */
   if (rewrite_uses_p (stmt))
-    {
-      FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
-       maybe_replace_use (use_p);
-
-      if (need_to_update_vops_p)
-       FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_VIRTUAL_USES)
-         maybe_replace_use (use_p);
-    }
+    FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES)
+      maybe_replace_use (use_p);
 
   /* Register definitions of names in NEW_SSA_NAMES and OLD_SSA_NAMES.
      Also register definitions for names whose underlying symbol is
      marked for renaming.  */
   if (register_defs_p (stmt))
-    {
-      FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, iter, SSA_OP_DEF)
-       maybe_register_def (def_p, stmt);
-
-      if (need_to_update_vops_p)
-       FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, iter, SSA_OP_VIRTUAL_DEFS)
-         maybe_register_def (def_p, stmt);
-    }
+    FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, iter, SSA_OP_ALL_DEFS)
+      maybe_register_def (def_p, stmt);
 }
 
 
@@ -2293,6 +2278,7 @@ struct gimple_opt_pass pass_build_ssa =
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
   TODO_dump_func
+    | TODO_update_ssa_only_virtuals
     | TODO_verify_ssa
     | TODO_remove_unused_locals                /* todo_flags_finish */
  }
@@ -2577,7 +2563,7 @@ dump_update_ssa (FILE *file)
   unsigned i = 0;
   bitmap_iterator bi;
 
-  if (!need_ssa_update_p ())
+  if (!need_ssa_update_p (cfun))
     return;
 
   if (new_ssa_names && sbitmap_first_set_bit (new_ssa_names) >= 0)
@@ -2604,10 +2590,11 @@ dump_update_ssa (FILE *file)
               update_ssa_stats.num_virtual_symbols);
     }
 
-  if (syms_to_rename && !bitmap_empty_p (syms_to_rename))
+  if (!bitmap_empty_p (SYMS_TO_RENAME (cfun)))
     {
       fprintf (file, "\n\nSymbols to be put in SSA form\n\n");
-      dump_decl_set (file, syms_to_rename);
+      dump_decl_set (file, SYMS_TO_RENAME (cfun));
+      fprintf (file, "\n");
     }
 
   if (names_to_release && !bitmap_empty_p (names_to_release))
@@ -2636,7 +2623,7 @@ debug_update_ssa (void)
 /* Initialize data structures used for incremental SSA updates.  */
 
 static void
-init_update_ssa (void)
+init_update_ssa (struct function *fn)
 {
   /* Reserve more space than the current number of names.  The calls to
      add_new_name_mapping are typically done after creating new SSA
@@ -2648,14 +2635,12 @@ init_update_ssa (void)
   sbitmap_zero (new_ssa_names);
 
   repl_tbl = htab_create (20, repl_map_hash, repl_map_eq, repl_map_free);
-  need_to_initialize_update_ssa_p = false;
-  need_to_update_vops_p = false;
-  syms_to_rename = BITMAP_ALLOC (NULL);
   regs_to_rename = BITMAP_ALLOC (NULL);
   mem_syms_to_rename = BITMAP_ALLOC (NULL);
   names_to_release = NULL;
   memset (&update_ssa_stats, 0, sizeof (update_ssa_stats));
   update_ssa_stats.virtual_symbols = BITMAP_ALLOC (NULL);
+  update_ssa_initialized_fn = fn;
 }
 
 
@@ -2676,9 +2661,7 @@ delete_update_ssa (void)
   htab_delete (repl_tbl);
   repl_tbl = NULL;
 
-  need_to_initialize_update_ssa_p = true;
-  need_to_update_vops_p = false;
-  BITMAP_FREE (syms_to_rename);
+  bitmap_clear (SYMS_TO_RENAME (update_ssa_initialized_fn));
   BITMAP_FREE (regs_to_rename);
   BITMAP_FREE (mem_syms_to_rename);
   BITMAP_FREE (update_ssa_stats.virtual_symbols);
@@ -2705,6 +2688,7 @@ delete_update_ssa (void)
 
   BITMAP_FREE (blocks_with_phis_to_rewrite);
   BITMAP_FREE (blocks_to_update);
+  update_ssa_initialized_fn = NULL;
 }
 
 
@@ -2751,12 +2735,14 @@ create_new_def_for (tree old_name, gimple stmt, def_operand_p def)
    update_ssa.  */
 
 void
-register_new_name_mapping (tree new_Tree ATTRIBUTE_UNUSED, tree old ATTRIBUTE_UNUSED)
+register_new_name_mapping (tree new_tree, tree old)
 {
-  if (need_to_initialize_update_ssa_p)
-    init_update_ssa ();
+  if (!update_ssa_initialized_fn)
+    init_update_ssa (cfun);
+
+  gcc_assert (update_ssa_initialized_fn == cfun);
 
-  add_new_name_mapping (new_Tree, old);
+  add_new_name_mapping (new_tree, old);
 }
 
 
@@ -2765,17 +2751,7 @@ register_new_name_mapping (tree new_Tree ATTRIBUTE_UNUSED, tree old ATTRIBUTE_UN
 void
 mark_sym_for_renaming (tree sym)
 {
-  if (need_to_initialize_update_ssa_p)
-    init_update_ssa ();
-
-  bitmap_set_bit (syms_to_rename, DECL_UID (sym));
-
-  if (!is_gimple_reg (sym))
-    {
-      need_to_update_vops_p = true;
-      if (memory_partition (sym))
-       bitmap_set_bit (syms_to_rename, DECL_UID (memory_partition (sym)));
-    }
+  bitmap_set_bit (SYMS_TO_RENAME (cfun), DECL_UID (sym));
 }
 
 
@@ -2790,20 +2766,21 @@ mark_set_for_renaming (bitmap set)
   if (set == NULL || bitmap_empty_p (set))
     return;
 
-  if (need_to_initialize_update_ssa_p)
-    init_update_ssa ();
-
   EXECUTE_IF_SET_IN_BITMAP (set, 0, i, bi)
     mark_sym_for_renaming (referenced_var (i));
 }
 
 
-/* Return true if there is any work to be done by update_ssa.  */
+/* Return true if there is any work to be done by update_ssa
+   for function FN.  */
 
 bool
-need_ssa_update_p (void)
+need_ssa_update_p (struct function *fn)
 {
-  return syms_to_rename || old_ssa_names || new_ssa_names;
+  gcc_assert (fn != NULL);
+  return (update_ssa_initialized_fn == fn
+         || (fn->gimple_df
+             && !bitmap_empty_p (SYMS_TO_RENAME (fn))));
 }
 
 /* Return true if SSA name mappings have been registered for SSA updating.  */
@@ -2811,6 +2788,11 @@ need_ssa_update_p (void)
 bool
 name_mappings_registered_p (void)
 {
+  if (!update_ssa_initialized_fn)
+    return false;
+
+  gcc_assert (update_ssa_initialized_fn == cfun);
+
   return repl_tbl && htab_elements (repl_tbl) > 0;
 }
 
@@ -2819,12 +2801,12 @@ name_mappings_registered_p (void)
 bool
 name_registered_for_update_p (tree n ATTRIBUTE_UNUSED)
 {
-  if (!need_ssa_update_p ())
+  if (!update_ssa_initialized_fn)
     return false;
 
-  return is_new_name (n)
-         || is_old_name (n)
-        || symbol_marked_for_renaming (SSA_NAME_VAR (n));
+  gcc_assert (update_ssa_initialized_fn == cfun);
+
+  return is_new_name (n) || is_old_name (n);
 }
 
 
@@ -2837,6 +2819,9 @@ ssa_names_to_replace (void)
   bitmap ret;
   sbitmap_iterator sbi;
   
+  gcc_assert (update_ssa_initialized_fn == NULL
+             || update_ssa_initialized_fn == cfun);
+
   ret = BITMAP_ALLOC (NULL);
   EXECUTE_IF_SET_IN_SBITMAP (old_ssa_names, 0, i, sbi)
     bitmap_set_bit (ret, i);
@@ -2850,7 +2835,7 @@ ssa_names_to_replace (void)
 void
 release_ssa_name_after_update_ssa (tree name)
 {
-  gcc_assert (!need_to_initialize_update_ssa_p);
+  gcc_assert (cfun && update_ssa_initialized_fn == cfun);
 
   if (names_to_release == NULL)
     names_to_release = BITMAP_ALLOC (NULL);
@@ -3110,11 +3095,15 @@ update_ssa (unsigned update_flags)
   bool insert_phi_p;
   sbitmap_iterator sbi;
 
-  if (!need_ssa_update_p ())
+  if (!need_ssa_update_p (cfun))
     return;
 
   timevar_push (TV_TREE_SSA_INCREMENTAL);
 
+  if (!update_ssa_initialized_fn)
+    init_update_ssa (cfun);
+  gcc_assert (update_ssa_initialized_fn == cfun);
+
   blocks_with_phis_to_rewrite = BITMAP_ALLOC (NULL);
   if (!phis_to_rewrite)
     phis_to_rewrite = VEC_alloc (gimple_vec, heap, last_basic_block);
@@ -3166,30 +3155,21 @@ update_ssa (unsigned update_flags)
   /* If there are symbols to rename, identify those symbols that are
      GIMPLE registers into the set REGS_TO_RENAME and those that are
      memory symbols into the set MEM_SYMS_TO_RENAME.  */
-  if (!bitmap_empty_p (syms_to_rename))
+  if (!bitmap_empty_p (SYMS_TO_RENAME (cfun)))
     {
       unsigned i;
       bitmap_iterator bi;
 
-      EXECUTE_IF_SET_IN_BITMAP (syms_to_rename, 0, i, bi)
+      EXECUTE_IF_SET_IN_BITMAP (SYMS_TO_RENAME (cfun), 0, i, bi)
        {
          tree sym = referenced_var (i);
          if (is_gimple_reg (sym))
            bitmap_set_bit (regs_to_rename, i);
-         else
-           {
-             /* Memory partitioning information may have been
-                computed after the symbol was marked for renaming,
-                if SYM is inside a partition also mark the partition
-                for renaming.  */
-             tree mpt = memory_partition (sym);
-             if (mpt)
-               bitmap_set_bit (syms_to_rename, DECL_UID (mpt));
-           }
        }
 
       /* Memory symbols are those not in REGS_TO_RENAME.  */
-      bitmap_and_compl (mem_syms_to_rename, syms_to_rename, regs_to_rename);
+      bitmap_and_compl (mem_syms_to_rename,
+                       SYMS_TO_RENAME (cfun), regs_to_rename);
     }
 
   /* If there are names defined in the replacement table, prepare
@@ -3203,12 +3183,12 @@ update_ssa (unsigned update_flags)
         removal, and there are no symbols to rename, then there's
         nothing else to do.  */
       if (sbitmap_first_set_bit (new_ssa_names) < 0
-         && bitmap_empty_p (syms_to_rename))
+         && bitmap_empty_p (SYMS_TO_RENAME (cfun)))
        goto done;
     }
 
   /* Next, determine the block at which to start the renaming process.  */
-  if (!bitmap_empty_p (syms_to_rename))
+  if (!bitmap_empty_p (SYMS_TO_RENAME (cfun)))
     {
       /* If we have to rename some symbols from scratch, we need to
         start the process at the root of the CFG.  FIXME, it should
@@ -3262,7 +3242,7 @@ update_ssa (unsigned update_flags)
          sbitmap_free (tmp);
        }
 
-      EXECUTE_IF_SET_IN_BITMAP (syms_to_rename, 0, i, bi)
+      EXECUTE_IF_SET_IN_BITMAP (SYMS_TO_RENAME (cfun), 0, i, bi)
        insert_updated_phi_nodes_for (referenced_var (i), dfs, blocks_to_update,
                                      update_flags);
 
@@ -3283,7 +3263,7 @@ update_ssa (unsigned update_flags)
   EXECUTE_IF_SET_IN_SBITMAP (old_ssa_names, 0, i, sbi)
     set_current_def (ssa_name (i), NULL_TREE);
 
-  EXECUTE_IF_SET_IN_BITMAP (syms_to_rename, 0, i, bi)
+  EXECUTE_IF_SET_IN_BITMAP (SYMS_TO_RENAME (cfun), 0, i, bi)
     set_current_def (referenced_var (i), NULL_TREE);
 
   /* Now start the renaming process at START_BB.  */
index 219d17e..6176297 100644 (file)
@@ -77,9 +77,6 @@ static bitmap remaining_stmts;
    predecessor a node that writes to memory.  */
 static bitmap upstream_mem_writes;
 
-/* TODOs we need to run after the pass.  */
-static unsigned int todo;
-
 /* Update the PHI nodes of NEW_LOOP.  NEW_LOOP is a duplicate of
    ORIG_LOOP.  */
 
@@ -241,14 +238,13 @@ static bool
 generate_memset_zero (gimple stmt, tree op0, tree nb_iter,
                      gimple_stmt_iterator bsi)
 {
-  tree t, addr_base;
+  tree addr_base;
   tree nb_bytes = NULL;
   bool res = false;
   gimple_seq stmts = NULL, stmt_list = NULL;
   gimple fn_call;
   tree mem, fndecl, fntype, fn;
   gimple_stmt_iterator i;
-  ssa_op_iter iter;
   struct data_reference *dr = XCNEW (struct data_reference);
 
   DR_STMT (dr) = stmt;
@@ -303,29 +299,6 @@ generate_memset_zero (gimple stmt, tree op0, tree nb_iter,
     {
       gimple s = gsi_stmt (i);
       update_stmt_if_modified (s);
-
-      FOR_EACH_SSA_TREE_OPERAND (t, s, iter, SSA_OP_VIRTUAL_DEFS)
-       {
-         if (TREE_CODE (t) == SSA_NAME)
-           t = SSA_NAME_VAR (t);
-         mark_sym_for_renaming (t);
-       }
-    }
-
-  /* Mark also the uses of the VDEFS of STMT to be renamed.  */
-  FOR_EACH_SSA_TREE_OPERAND (t, stmt, iter, SSA_OP_VIRTUAL_DEFS)
-    {
-      if (TREE_CODE (t) == SSA_NAME)
-       {
-         gimple s;
-         imm_use_iterator imm_iter;
-
-         FOR_EACH_IMM_USE_STMT (s, imm_iter, t)
-           update_stmt (s);
-
-         t = SSA_NAME_VAR (t);
-       }
-      mark_sym_for_renaming (t);
     }
 
   gsi_insert_seq_after (&bsi, stmt_list, GSI_CONTINUE_LINKING);
@@ -334,8 +307,6 @@ generate_memset_zero (gimple stmt, tree op0, tree nb_iter,
   if (dump_file && (dump_flags & TDF_DETAILS))
     fprintf (dump_file, "generated memset zero\n");
 
-  todo |= TODO_rebuild_alias;
-
  end:
   free_data_ref (dr);
   return res;
@@ -606,7 +577,6 @@ static void
 rdg_flag_uses (struct graph *rdg, int u, bitmap partition, bitmap loops,
               bitmap processed, bool *part_has_writes)
 {
-  ssa_op_iter iter;
   use_operand_p use_p;
   struct vertex *x = &(rdg->vertices[u]);
   gimple stmt = RDGV_STMT (x);
@@ -626,7 +596,7 @@ rdg_flag_uses (struct graph *rdg, int u, bitmap partition, bitmap loops,
 
   if (gimple_code (stmt) != GIMPLE_PHI)
     {
-      FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_VIRTUAL_USES)
+      if ((use_p = gimple_vuse_op (stmt)) != NULL_USE_OPERAND_P)
        {
          tree use = USE_FROM_PTR (use_p);
 
@@ -1211,8 +1181,6 @@ tree_loop_distribution (void)
   loop_iterator li;
   int nb_generated_loops = 0;
 
-  todo = 0;
-
   FOR_EACH_LOOP (li, loop, 0)
     {
       VEC (gimple, heap) *work_list = VEC_alloc (gimple, heap, 3);
@@ -1244,7 +1212,7 @@ tree_loop_distribution (void)
       VEC_free (gimple, heap, work_list);
     }
 
-  return todo;
+  return 0;
 }
 
 static bool
index 82cc0ff..19e49d5 100644 (file)
@@ -122,14 +122,10 @@ create_temp (tree t)
   DECL_GIMPLE_REG_P (tmp) = DECL_GIMPLE_REG_P (t);
   add_referenced_var (tmp);
 
-  /* add_referenced_var will create the annotation and set up some
-     of the flags in the annotation.  However, some flags we need to
-     inherit from our original variable.  */
-  set_symbol_mem_tag (tmp, symbol_mem_tag (t));
-  if (is_call_clobbered (t))
-    mark_call_clobbered (tmp, var_ann (t)->escape_mask);
-  if (bitmap_bit_p (gimple_call_used_vars (cfun), DECL_UID (t)))
-    bitmap_set_bit (gimple_call_used_vars (cfun), DECL_UID (tmp));
+  /* We should never have copied variables in non-automatic storage
+     or variables that have their address taken.  So it is pointless
+     to try to copy call-clobber state here.  */
+  gcc_assert (!may_be_aliased (t) && !is_global_var (t));
 
   return tmp;
 }
index 2db0f22..cc9a80c 100644 (file)
@@ -286,7 +286,10 @@ struct dump_file_info
 #define TODO_mark_first_instance       (1 << 19)
 
 /* Rebuild aliasing info.  */
-#define TODO_rebuild_alias                (1 << 20)
+#define TODO_rebuild_alias              (1 << 20)
+
+/* Rebuild the addressable-vars bitmap and do register promotion.  */
+#define TODO_update_address_taken      (1 << 21)
 
 #define TODO_update_ssa_any            \
     (TODO_update_ssa                   \
@@ -374,7 +377,6 @@ extern struct gimple_opt_pass pass_forwprop;
 extern struct gimple_opt_pass pass_phiprop;
 extern struct gimple_opt_pass pass_tree_ifcombine;
 extern struct gimple_opt_pass pass_dse;
-extern struct gimple_opt_pass pass_simple_dse;
 extern struct gimple_opt_pass pass_nrv;
 extern struct gimple_opt_pass pass_mark_used_blocks;
 extern struct gimple_opt_pass pass_rename_ssa_copies;
@@ -391,7 +393,6 @@ extern struct gimple_opt_pass pass_reassoc;
 extern struct gimple_opt_pass pass_rebuild_cgraph_edges;
 extern struct gimple_opt_pass pass_remove_cgraph_callee_edges;
 extern struct gimple_opt_pass pass_build_cgraph_edges;
-extern struct gimple_opt_pass pass_reset_cc_flags;
 extern struct gimple_opt_pass pass_local_pure_const;
 
 /* IPA Passes */
index bd82a80..a5d4dcd 100644 (file)
@@ -1423,7 +1423,6 @@ get_init_expr (chain_p chain, unsigned index)
 void
 mark_virtual_ops_for_renaming (gimple stmt)
 {
-  ssa_op_iter iter;
   tree var;
 
   if (gimple_code (stmt) == GIMPLE_PHI)
@@ -1439,24 +1438,8 @@ mark_virtual_ops_for_renaming (gimple stmt)
     }
 
   update_stmt (stmt);
-
-  FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_ALL_VIRTUALS)
-    {
-      if (TREE_CODE (var) == SSA_NAME)
-       var = SSA_NAME_VAR (var);
-      mark_sym_for_renaming (var);
-    }
-}
-
-/* Calls mark_virtual_ops_for_renaming for all members of LIST.  */
-
-static void
-mark_virtual_ops_for_renaming_list (gimple_seq list)
-{
-  gimple_stmt_iterator gsi;
-
-  for (gsi = gsi_start (list); !gsi_end_p (gsi); gsi_next (&gsi))
-    mark_virtual_ops_for_renaming (gsi_stmt (gsi));
+  if (gimple_vuse (stmt))
+    mark_sym_for_renaming (gimple_vop (cfun));
 }
 
 /* Returns a new temporary variable used for the I-th variable carrying
@@ -1525,10 +1508,7 @@ initialize_root_vars (struct loop *loop, chain_p chain, bitmap tmp_vars)
 
       init = force_gimple_operand (init, &stmts, true, NULL_TREE);
       if (stmts)
-       {
-         mark_virtual_ops_for_renaming_list (stmts);
-         gsi_insert_seq_on_edge_immediate (entry, stmts);
-       }
+       gsi_insert_seq_on_edge_immediate (entry, stmts);
 
       phi = create_phi_node (var, loop->header);
       SSA_NAME_DEF_STMT (var) = phi;
@@ -1589,10 +1569,7 @@ initialize_root_vars_lm (struct loop *loop, dref root, bool written,
       
   init = force_gimple_operand (init, &stmts, written, NULL_TREE);
   if (stmts)
-    {
-      mark_virtual_ops_for_renaming_list (stmts);
-      gsi_insert_seq_on_edge_immediate (entry, stmts);
-    }
+    gsi_insert_seq_on_edge_immediate (entry, stmts);
 
   if (written)
     {
@@ -2421,31 +2398,6 @@ try_combine_chains (VEC (chain_p, heap) **chains)
     }
 }
 
-/* Sets alias information based on data reference DR for REF,
-   if necessary.  */
-
-static void
-set_alias_info (tree ref, struct data_reference *dr)
-{
-  tree var;
-  tree tag = DR_SYMBOL_TAG (dr);
-
-  gcc_assert (tag != NULL_TREE);
-
-  ref = get_base_address (ref);
-  if (!ref || !INDIRECT_REF_P (ref))
-    return;
-
-  var = SSA_NAME_VAR (TREE_OPERAND (ref, 0));
-  if (var_ann (var)->symbol_mem_tag)
-    return;
-
-  if (!MTAG_P (tag))
-    new_type_alias (var, tag, ref);
-  else
-    var_ann (var)->symbol_mem_tag = tag;
-}
-
 /* Prepare initializers for CHAIN in LOOP.  Returns false if this is
    impossible because one of these initializers may trap, true otherwise.  */
 
@@ -2491,11 +2443,7 @@ prepare_initializers_chain (struct loop *loop, chain_p chain)
 
       init = force_gimple_operand (init, &stmts, false, NULL_TREE);
       if (stmts)
-       {
-         mark_virtual_ops_for_renaming_list (stmts);
-         gsi_insert_seq_on_edge_immediate (entry, stmts);
-       }
-      set_alias_info (init, dr);
+       gsi_insert_seq_on_edge_immediate (entry, stmts);
 
       VEC_replace (tree, chain->inits, i, init);
     }
index ff45ecc..a497ca7 100644 (file)
@@ -881,13 +881,10 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
        }
       break;
 
-    case SYMBOL_MEMORY_TAG:
-    case NAME_MEMORY_TAG:
     case VAR_DECL:
     case PARM_DECL:
     case FIELD_DECL:
     case NAMESPACE_DECL:
-    case MEMORY_PARTITION_TAG:
       dump_decl_name (buffer, node, flags);
       break;
 
index 6149ff5..f0e4bd0 100644 (file)
@@ -78,9 +78,6 @@ along with GCC; see the file COPYING3.  If not see
 /* True if this is the "early" pass, before inlining.  */
 static bool early_sra;
 
-/* The set of todo flags to return from tree_sra.  */
-static unsigned int todoflags;
-
 /* The set of aggregate variables that are candidates for scalarization.  */
 static bitmap sra_candidates;
 
@@ -210,7 +207,6 @@ extern void debug_sra_elt_name (struct sra_elt *);
 static tree generate_element_ref (struct sra_elt *);
 static gimple_seq sra_build_assignment (tree dst, tree src);
 static void mark_all_v_defs_seq (gimple_seq);
-static void mark_all_v_defs_stmt (gimple);
 
 \f
 /* Return true if DECL is an SRA candidate.  */
@@ -1057,11 +1053,10 @@ sra_walk_function (const struct sra_walk_fns *fns)
        ni = si;
        gsi_next (&ni);
 
-       /* If the statement has no virtual operands, then it doesn't
+       /* If the statement does not reference memory, then it doesn't
           make any structure references that we care about.  */
-       if (gimple_aliases_computed_p (cfun)
-           && ZERO_SSA_OPERANDS (stmt, (SSA_OP_VIRTUAL_DEFS | SSA_OP_VUSE)))
-             continue;
+       if (!gimple_references_memory_p (stmt))
+         continue;
 
        switch (gimple_code (stmt))
          {
@@ -2008,27 +2003,6 @@ decide_instantiations (void)
 \f
 /* Phase Four: Update the function to match the replacements created.  */
 
-/* Mark all the variables in VDEF/VUSE operators for STMT for
-   renaming. This becomes necessary when we modify all of a
-   non-scalar.  */
-
-static void
-mark_all_v_defs_stmt (gimple stmt)
-{
-  tree sym;
-  ssa_op_iter iter;
-
-  update_stmt_if_modified (stmt);
-
-  FOR_EACH_SSA_TREE_OPERAND (sym, stmt, iter, SSA_OP_ALL_VIRTUALS)
-    {
-      if (TREE_CODE (sym) == SSA_NAME)
-       sym = SSA_NAME_VAR (sym);
-      mark_sym_for_renaming (sym);
-    }
-}
-
-
 /* Mark all the variables in virtual operands in all the statements in
    LIST for renaming.  */
 
@@ -2038,7 +2012,7 @@ mark_all_v_defs_seq (gimple_seq seq)
   gimple_stmt_iterator gsi;
 
   for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
-    mark_all_v_defs_stmt (gsi_stmt (gsi));
+    update_stmt_if_modified (gsi_stmt (gsi));
 }
 
 /* Mark every replacement under ELT with TREE_NO_WARNING.  */
@@ -2863,6 +2837,7 @@ static void
 sra_replace (gimple_stmt_iterator *gsi, gimple_seq seq)
 {
   sra_insert_before (gsi, seq);
+  unlink_stmt_vdef (gsi_stmt (*gsi));
   gsi_remove (gsi, false);
   if (gsi_end_p (*gsi))
     *gsi = gsi_last (gsi_seq (*gsi));
@@ -3138,7 +3113,7 @@ scalarize_use (struct sra_elt *elt, tree *expr_p, gimple_stmt_iterator *gsi,
          replacement = tmp;
        }
       if (is_output)
-         mark_all_v_defs_stmt (stmt);
+         update_stmt_if_modified (stmt);
       *expr_p = REPLDUP (replacement);
       update_stmt (stmt);
     }
@@ -3358,7 +3333,7 @@ scalarize_copy (struct sra_elt *lhs_elt, struct sra_elt *rhs_elt,
         original block copy statement.  */
 
       stmt = gsi_stmt (*gsi);
-      mark_all_v_defs_stmt (stmt);
+      update_stmt_if_modified (stmt);
 
       seq = NULL;
       generate_element_copy (lhs_elt, rhs_elt, &seq);
@@ -3425,7 +3400,7 @@ scalarize_init (struct sra_elt *lhs_elt, tree rhs, gimple_stmt_iterator *gsi)
       /* The LHS is fully instantiated.  The list of initializations
         replaces the original structure assignment.  */
       gcc_assert (seq);
-      mark_all_v_defs_stmt (gsi_stmt (*gsi));
+      update_stmt_if_modified (gsi_stmt (*gsi));
       mark_all_v_defs_seq (seq);
       sra_replace (gsi, seq);
     }
@@ -3476,7 +3451,7 @@ scalarize_ldst (struct sra_elt *elt, tree other,
       gimple_seq seq = NULL;
       gimple stmt = gsi_stmt (*gsi);
 
-      mark_all_v_defs_stmt (stmt);
+      update_stmt_if_modified (stmt);
       generate_copy_inout (elt, is_output, other, &seq);
       gcc_assert (seq);
       mark_all_v_defs_seq (seq);
@@ -3637,7 +3612,6 @@ static unsigned int
 tree_sra (void)
 {
   /* Initialize local variables.  */
-  todoflags = 0;
   gcc_obstack_init (&sra_obstack);
   sra_candidates = BITMAP_ALLOC (NULL);
   needs_copy_in = BITMAP_ALLOC (NULL);
@@ -3650,8 +3624,6 @@ tree_sra (void)
       scan_function ();
       decide_instantiations ();
       scalarize_function ();
-      if (!bitmap_empty_p (sra_candidates))
-       todoflags |= TODO_rebuild_alias;
     }
 
   /* Free allocated memory.  */
@@ -3662,7 +3634,7 @@ tree_sra (void)
   BITMAP_FREE (sra_type_decomp_cache);
   BITMAP_FREE (sra_type_inst_cache);
   obstack_free (&sra_obstack, NULL);
-  return todoflags;
+  return 0;
 }
 
 static unsigned int
@@ -3674,7 +3646,7 @@ tree_sra_early (void)
   ret = tree_sra ();
   early_sra = false;
 
-  return ret & ~TODO_rebuild_alias;
+  return ret;
 }
 
 static bool
@@ -3719,7 +3691,7 @@ struct gimple_opt_pass pass_sra =
   PROP_cfg | PROP_ssa,                 /* properties_required */
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
-  0,                                   /* todo_flags_start */
+  TODO_update_address_taken,           /* todo_flags_start */
   TODO_dump_func
   | TODO_update_ssa
   | TODO_ggc_collect
index 6c81b09..f9cd530 100644 (file)
@@ -333,9 +333,9 @@ create_mem_ref_raw (tree type, struct mem_address *addr)
   if (addr->offset && integer_zerop (addr->offset))
     addr->offset = NULL_TREE;
 
-  return build7 (TARGET_MEM_REF, type,
+  return build6 (TARGET_MEM_REF, type,
                 addr->symbol, addr->base, addr->index,
-                addr->step, addr->offset, NULL, NULL);
+                addr->step, addr->offset, NULL);
 }
 
 /* Returns true if OBJ is an object whose address is a link time constant.  */
@@ -709,9 +709,6 @@ get_address_description (tree op, struct mem_address *addr)
 void
 copy_mem_ref_info (tree to, tree from)
 {
-  /* Copy the annotation, to preserve the aliasing information.  */
-  TMR_TAG (to) = TMR_TAG (from);
-
   /* And the info about the original reference.  */
   TMR_ORIGINAL (to) = TMR_ORIGINAL (from);
 }
index 4dd4fb7..a85858e 100644 (file)
@@ -40,7 +40,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-flow.h"
 #include "tree-inline.h"
 #include "tree-pass.h"
-#include "tree-ssa-structalias.h"
 #include "convert.h"
 #include "params.h"
 #include "ipa-type-escape.h"
@@ -49,3078 +48,183 @@ along with GCC; see the file COPYING3.  If not see
 #include "vecprim.h"
 #include "pointer-set.h"
 #include "alloc-pool.h"
+#include "tree-ssa-alias.h"
 
-/* Broad overview of how aliasing works:
-   
-   First we compute points-to sets, which is done in
-   tree-ssa-structalias.c
-      
-   During points-to set constraint finding, a bunch of little bits of
-   information is collected.
-   This is not done because it is necessary for points-to, but because
-   points-to has to walk every statement anyway.  The function performing
-   this collecting is update_alias_info.
-
-   Bits update_alias_info collects include:
-   1. Directly escaping variables and variables whose value escapes
-   (using is_escape_site).  This is the set of variables and values that
-   escape prior to transitive closure of the clobbers.
-   2.  The set of variables dereferenced on the LHS (into
-   dereferenced_ptr_stores) 
-   3. The set of variables dereferenced on the RHS (into
-   dereferenced_ptr_loads) 
-   4. The set of all pointers we saw.
-   5. The number of loads and stores for each variable
-   6. The number of statements touching memory
-   7. The set of address taken variables.
-   
-   
-   #1 is computed by a combination of is_escape_site, and counting the
-   number of uses/deref operators.  This function properly accounts for
-   situations like &ptr->field, which is *not* a dereference.
-   
-   After points-to sets are computed, the sets themselves still
-   contain points-to specific variables, such as a variable that says
-   the pointer points to anything, a variable that says the pointer
-   points to readonly memory, etc.
-
-   These are eliminated in a later phase, as we will see.
-
-   The rest of the phases are located in tree-ssa-alias.c
-
-   The next phase after points-to set computation is called
-   "setup_pointers_and_addressables"
-
-   This pass does 3 main things:
-   
-   1. All variables that can have TREE_ADDRESSABLE removed safely (IE
-   non-globals whose address is not taken), have TREE_ADDRESSABLE
-   removed.
-   2. All variables that may be aliased (which is the set of addressable
-   variables and globals) at all, are marked for renaming, and have
-   symbol memory tags created for them.
-   3. All variables which are stored into have their SMT's added to
-   written vars. 
-
-
-   After this function is run, all variables that will ever have an
-   SMT, have one, though its aliases are not filled in.
-
-   The next phase is to compute flow-insensitive aliasing, which in
-   our case, is a misnomer.  it is really computing aliasing that
-   requires no transitive closure to be correct.  In particular, it
-   uses stack vs non-stack, TBAA, etc, to determine whether two
-   symbols could *ever* alias .  This phase works by going through all
-   the pointers we collected during update_alias_info, and for every
-   addressable variable in the program, seeing if they alias.  If so,
-   the addressable variable is added to the symbol memory tag for the
-   pointer.
-
-   As part of this, we handle symbol memory tags that conflict but
-   have no aliases in common, by forcing them to have a symbol in
-   common (through unioning alias sets or adding one as an alias of
-   the other), or by adding one as an alias of another.  The case of
-   conflicts with no aliases in common occurs mainly due to aliasing
-   we cannot see.  In particular, it generally means we have a load
-   through a pointer whose value came from outside the function.
-   Without an addressable symbol to point to, they would get the wrong
-   answer.
-
-   After flow insensitive aliasing is computed, we compute name tags
-   (called compute_flow_sensitive_info).  We walk each pointer we
-   collected and see if it has a usable points-to set.  If so, we
-   generate a name tag using that pointer, and make an alias bitmap for
-   it.  Name tags are shared between all things with the same alias
-   bitmap.  The alias bitmap will be translated from what points-to
-   computed.  In particular, the "anything" variable in points-to will be
-   transformed into a pruned set of SMT's and their aliases that
-   compute_flow_insensitive_aliasing computed.
-   Note that since 4.3, every pointer that points-to computed a solution for
-   will get a name tag (whereas before 4.3, only those whose set did
-   *not* include the anything variable would).  At the point where name
-   tags are all assigned, symbol memory tags are dead, and could be
-   deleted, *except* on global variables.  Global variables still use
-   symbol memory tags as of right now.
-
-   After name tags are computed, the set of clobbered variables is
-   transitively closed.  In particular, we compute the set of clobbered
-   variables based on the initial set of clobbers, plus the aliases of
-   pointers which either escape, or have their value escape.
-
-   After this, maybe_create_global_var is run, which handles a corner
-   case where we have no call clobbered variables, but have pure and
-   non-pure functions.
-   
-   Staring at this function, I now remember it is a hack for the fact
-   that we do not mark all globals in the program as call clobbered for a
-   function unless they are actually used in that function.  Instead,  we
-   only mark the set that is actually clobbered.  As a result, you can
-   end up with situations where you have no call clobbered vars set.
-   
-   After maybe_create_global_var, we set pointers with the REF_ALL flag
-   to have alias sets that include all clobbered
-   memory tags and variables.
-   
-   After this, memory partitioning is computed (by the function
-   compute_memory_partitions) and alias sets are reworked accordingly.
-
-   Lastly, we delete partitions with no symbols, and clean up after
-   ourselves.  */
-
-
-/* Alias information used by compute_may_aliases and its helpers.  */
-struct alias_info
-{
-  /* SSA names visited while collecting points-to information.  If bit I
-     is set, it means that SSA variable with version I has already been
-     visited.  */
-  sbitmap ssa_names_visited;
-
-  /* Array of SSA_NAME pointers processed by the points-to collector.  */
-  VEC(tree,heap) *processed_ptrs;
-
-  /* ADDRESSABLE_VARS contains all the global variables and locals that
-     have had their address taken.  */
-  struct alias_map_d **addressable_vars;
-  size_t num_addressable_vars;
-
-  /* POINTERS contains all the _DECL pointers with unique memory tags
-     that have been referenced in the program.  */
-  struct alias_map_d **pointers;
-  size_t num_pointers;
-
-  /* Pointers that have been used in an indirect load/store operation.  */
-  struct pointer_set_t *dereferenced_ptrs;
-};
-
-
-/* Structure to map a variable to its alias set.  */
-struct alias_map_d
-{
-  /* Variable and its alias set.  */
-  tree var;
-  alias_set_type set;
-};
-
-
-/* Counters used to display statistics on alias analysis.  */
-struct alias_stats_d
-{
-  unsigned int alias_queries;
-  unsigned int alias_mayalias;
-  unsigned int alias_noalias;
-  unsigned int simple_queries;
-  unsigned int simple_resolved;
-  unsigned int tbaa_queries;
-  unsigned int tbaa_resolved;
-  unsigned int structnoaddress_queries;
-  unsigned int structnoaddress_resolved;
-};
-
-
-/* Local variables.  */
-static struct alias_stats_d alias_stats;
-static bitmap_obstack alias_bitmap_obstack;
-
-/* Local functions.  */
-static void compute_flow_insensitive_aliasing (struct alias_info *);
-static void dump_alias_stats (FILE *);
-static tree create_memory_tag (tree type, bool is_type_tag);
-static tree get_smt_for (tree, struct alias_info *);
-static tree get_nmt_for (tree);
-static void add_may_alias (tree, tree);
-static struct alias_info *init_alias_info (void);
-static void delete_alias_info (struct alias_info *);
-static void compute_flow_sensitive_aliasing (struct alias_info *);
-static void setup_pointers_and_addressables (struct alias_info *);
-static void update_alias_info (struct alias_info *);
-static void create_global_var (void);
-static void maybe_create_global_var (void);
-static void set_pt_anything (tree);
-
-void debug_mp_info (VEC(mem_sym_stats_t,heap) *);
-
-static alloc_pool mem_sym_stats_pool;
-
-/* Return memory reference stats for symbol VAR.  Create a new slot in
-   cfun->gimple_df->mem_sym_stats if needed.  */
-
-static struct mem_sym_stats_d *
-get_mem_sym_stats_for (tree var)
-{
-  void **slot;
-  struct mem_sym_stats_d *stats;
-  struct pointer_map_t *map = gimple_mem_ref_stats (cfun)->mem_sym_stats;
-  
-  gcc_assert (map);
-
-  slot = pointer_map_insert (map, var);
-  if (*slot == NULL)
-    {
-      stats = (struct mem_sym_stats_d *) pool_alloc (mem_sym_stats_pool);
-      memset (stats, 0, sizeof (*stats));
-      stats->var = var;
-      *slot = (void *) stats;
-    }
-  else
-    stats = (struct mem_sym_stats_d *) *slot;
-
-  return stats;
-}
-
-
-/* Return memory reference statistics for variable VAR in function FN.
-   This is computed by alias analysis, but it is not kept
-   incrementally up-to-date.  So, these stats are only accurate if
-   pass_may_alias has been run recently.  If no alias information
-   exists, this function returns NULL.  */
-
-static mem_sym_stats_t
-mem_sym_stats (struct function *fn, tree var)
-{
-  void **slot;
-  struct pointer_map_t *stats_map = gimple_mem_ref_stats (fn)->mem_sym_stats;
-
-  if (stats_map == NULL)
-    return NULL;
-
-  slot = pointer_map_contains (stats_map, var);
-  if (slot == NULL)
-    return NULL;
-
-  return (mem_sym_stats_t) *slot;
-}
-
-
-/* Set MPT to be the memory partition associated with symbol SYM.  */
-
-static inline void
-set_memory_partition (tree sym, tree mpt)
-{
-#if defined ENABLE_CHECKING
-  if (mpt)
-    gcc_assert (TREE_CODE (mpt) == MEMORY_PARTITION_TAG
-               && !is_gimple_reg (sym));
-#endif
-
-  var_ann (sym)->mpt = mpt;
-  if (mpt)
-    {
-      if (MPT_SYMBOLS (mpt) == NULL)
-       MPT_SYMBOLS (mpt) = BITMAP_ALLOC (&alias_bitmap_obstack);
-
-      bitmap_set_bit (MPT_SYMBOLS (mpt), DECL_UID (sym));
-
-      /* MPT inherits the call-clobbering attributes from SYM.  */
-      if (is_call_clobbered (sym))
-       {
-         MTAG_GLOBAL (mpt) = 1;
-         mark_call_clobbered (mpt, ESCAPE_IS_GLOBAL);
-       }
-    }
-}
-
-
-/* Mark variable VAR as being non-addressable.  */
-
-static void
-mark_non_addressable (tree var)
-{
-  tree mpt;
-
-  if (!TREE_ADDRESSABLE (var))
-    return;
-
-  mpt = memory_partition (var);
-
-  clear_call_clobbered (var);
-  TREE_ADDRESSABLE (var) = 0;
-
-  if (mpt)
-    {
-      /* Note that it's possible for a symbol to have an associated
-        MPT and the MPT have a NULL empty set.  During
-        init_alias_info, all MPTs get their sets cleared out, but the
-        symbols still point to the old MPTs that used to hold them.
-        This is done so that compute_memory_partitions can now which
-        symbols are losing or changing partitions and mark them for
-        renaming.  */
-      if (MPT_SYMBOLS (mpt))
-       bitmap_clear_bit (MPT_SYMBOLS (mpt), DECL_UID (var));
-      set_memory_partition (var, NULL_TREE);
-    }
-}
-
-
-/* qsort comparison function to sort type/name tags by DECL_UID.  */
-
-static int
-sort_tags_by_id (const void *pa, const void *pb)
-{
-  const_tree const a = *(const_tree const *)pa;
-  const_tree const b = *(const_tree const *)pb;
-  return DECL_UID (a) - DECL_UID (b);
-}
-
-/* Initialize WORKLIST to contain those memory tags that are marked call
-   clobbered.  Initialized WORKLIST2 to contain the reasons these
-   memory tags escaped.  */
-
-static void
-init_transitive_clobber_worklist (VEC (tree, heap) **worklist,
-                                 VEC (int, heap) **worklist2,
-                                 bitmap on_worklist)
-{
-  referenced_var_iterator rvi;
-  tree curr;
-
-  FOR_EACH_REFERENCED_VAR (curr, rvi)
-    {
-      if (MTAG_P (curr) && is_call_clobbered (curr))
-       {
-         VEC_safe_push (tree, heap, *worklist, curr);
-         VEC_safe_push (int, heap, *worklist2,
-                        var_ann (curr)->escape_mask);
-         bitmap_set_bit (on_worklist, DECL_UID (curr));
-       }
-    }
-}
-
-/* Add ALIAS to WORKLIST (and the reason for escaping REASON to WORKLIST2) if
-   ALIAS is not already marked call clobbered, and is a memory
-   tag.  */
-
-static void
-add_to_worklist (tree alias, VEC (tree, heap) **worklist,
-                VEC (int, heap) **worklist2, int reason,
-                bitmap on_worklist)
-{
-  if (MTAG_P (alias) && !is_call_clobbered (alias)
-      && !bitmap_bit_p (on_worklist, DECL_UID (alias)))
-    {
-      VEC_safe_push (tree, heap, *worklist, alias);
-      VEC_safe_push (int, heap, *worklist2, reason);
-      bitmap_set_bit (on_worklist, DECL_UID (alias));
-    }
-}
-
-/* Mark aliases of TAG as call clobbered, and place any tags on the
-   alias list that were not already call clobbered on WORKLIST.  */
-
-static void
-mark_aliases_call_clobbered (tree tag, VEC (tree, heap) **worklist,
-                            VEC (int, heap) **worklist2, bitmap on_worklist)
-{
-  bitmap aliases;
-  bitmap_iterator bi;
-  unsigned int i;
-  tree entry;
-  var_ann_t ta = var_ann (tag);
-
-  if (!MTAG_P (tag))
-    return;
-  aliases = may_aliases (tag);
-  if (!aliases)
-    return;
-
-  EXECUTE_IF_SET_IN_BITMAP (aliases, 0, i, bi)
-    {
-      entry = referenced_var (i);
-      /* If you clobber one part of a structure, you
-        clobber the entire thing.  While this does not make
-        the world a particularly nice place, it is necessary
-        in order to allow C/C++ tricks that involve
-        pointer arithmetic to work.  */
-      if (!unmodifiable_var_p (entry))
-       {
-         add_to_worklist (entry, worklist, worklist2, ta->escape_mask,
-                          on_worklist);
-         mark_call_clobbered (entry, ta->escape_mask);
-       }
-    }
-}
-
-/* Tags containing global vars need to be marked as global.
-   Tags containing call clobbered vars need to be marked as call
-   clobbered. */
-
-static void
-compute_tag_properties (void)
-{
-  referenced_var_iterator rvi;
-  tree tag;
-  bool changed = true;
-  VEC (tree, heap) *taglist = NULL;
-
-  FOR_EACH_REFERENCED_VAR (tag, rvi)
-    {
-      if (!MTAG_P (tag))
-       continue;
-      VEC_safe_push (tree, heap, taglist, tag);
-    }
-
-  /* We sort the taglist by DECL_UID, for two reasons.
-     1. To get a sequential ordering to make the bitmap accesses
-     faster.
-     2. Because of the way we compute aliases, it's more likely that
-     an earlier tag is included in a later tag, and this will reduce
-     the number of iterations.
-
-     If we had a real tag graph, we would just topo-order it and be
-     done with it.  */
-  qsort (VEC_address (tree, taglist),
-        VEC_length (tree, taglist),
-        sizeof (tree),
-        sort_tags_by_id);
-
-  /* Go through each tag not marked as global, and if it aliases
-     global vars, mark it global. 
-     
-     If the tag contains call clobbered vars, mark it call
-     clobbered.  
-
-     This loop iterates because tags may appear in the may-aliases
-     list of other tags when we group.  */
-
-  while (changed)
-    {
-      unsigned int k;
-
-      changed = false;      
-      for (k = 0; VEC_iterate (tree, taglist, k, tag); k++)
-       {
-         bitmap ma;
-         bitmap_iterator bi;
-         unsigned int i;
-         tree entry;
-         bool tagcc = is_call_clobbered (tag);
-         bool tagglobal = MTAG_GLOBAL (tag);
-         
-         if (tagcc && tagglobal)
-           continue;
-         
-         ma = may_aliases (tag);
-         if (!ma)
-           continue;
-
-         EXECUTE_IF_SET_IN_BITMAP (ma, 0, i, bi)
-           {
-             entry = referenced_var (i);
-             /* Call clobbered entries cause the tag to be marked
-                call clobbered.  */
-             if (!tagcc && is_call_clobbered (entry))
-               {
-                 mark_call_clobbered (tag, var_ann (entry)->escape_mask);
-                 tagcc = true;
-                 changed = true;
-               }
-
-             /* Global vars cause the tag to be marked global.  */
-             if (!tagglobal && is_global_var (entry))
-               {
-                 MTAG_GLOBAL (tag) = true;
-                 changed = true;
-                 tagglobal = true;
-               }
-
-             /* Early exit once both global and cc are set, since the
-                loop can't do any more than that.  */
-             if (tagcc && tagglobal)
-               break;
-           }
-       }
-    }
-  VEC_free (tree, heap, taglist);
-}
-
-/* Set up the initial variable clobbers, call-uses and globalness.
-   When this function completes, only tags whose aliases need to be
-   clobbered will be set clobbered.  Tags clobbered because they   
-   contain call clobbered vars are handled in compute_tag_properties.  */
-
-static void
-set_initial_properties (struct alias_info *ai)
-{
-  unsigned int i;
-  referenced_var_iterator rvi;
-  tree var;
-  tree ptr;
-  bool any_pt_anything = false;
-  enum escape_type pt_anything_mask = 0;
-
-  FOR_EACH_REFERENCED_VAR (var, rvi)
-    {
-      if (is_global_var (var))
-       {
-         if (!unmodifiable_var_p (var))
-           mark_call_clobbered (var, ESCAPE_IS_GLOBAL);
-       }
-      else if (TREE_CODE (var) == PARM_DECL
-              && gimple_default_def (cfun, var)
-              && POINTER_TYPE_P (TREE_TYPE (var)))
-       {
-         tree def = gimple_default_def (cfun, var);
-         get_ptr_info (def)->value_escapes_p = 1;
-         get_ptr_info (def)->escape_mask |= ESCAPE_IS_PARM;      
-       }
-    }
-
-  if (!clobber_what_escaped ())
-    {
-      any_pt_anything = true;
-      pt_anything_mask |= ESCAPE_TO_CALL;
-    }
-
-  compute_call_used_vars ();
-
-  for (i = 0; VEC_iterate (tree, ai->processed_ptrs, i, ptr); i++)
-    {
-      struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
-      tree tag = symbol_mem_tag (SSA_NAME_VAR (ptr));
-
-      /* A pointer that only escapes via a function return does not
-         add to the call clobber or call used solution.
-        To exclude ESCAPE_TO_PURE_CONST we would need to track
-        call used variables separately or compute those properly
-        in the operand scanner.  */
-      if (pi->value_escapes_p
-         && pi->escape_mask & ~ESCAPE_TO_RETURN)
-       {
-         /* If PTR escapes then its associated memory tags and
-            pointed-to variables are call-clobbered.  */
-         if (pi->name_mem_tag)
-           mark_call_clobbered (pi->name_mem_tag, pi->escape_mask);
-
-         if (tag)
-           mark_call_clobbered (tag, pi->escape_mask);
-       }
-
-      /* If the name tag is call clobbered, so is the symbol tag
-        associated with the base VAR_DECL.  */
-      if (pi->name_mem_tag
-         && tag
-         && is_call_clobbered (pi->name_mem_tag))
-       mark_call_clobbered (tag, pi->escape_mask);
-
-      /* Name tags and symbol tags that we don't know where they point
-        to, might point to global memory, and thus, are clobbered.
-
-         FIXME:  This is not quite right.  They should only be
-         clobbered if value_escapes_p is true, regardless of whether
-         they point to global memory or not.
-         So removing this code and fixing all the bugs would be nice.
-         It is the cause of a bunch of clobbering.  */
-      if ((pi->pt_global_mem || pi->pt_anything) 
-         && pi->memory_tag_needed && pi->name_mem_tag)
-       {
-         mark_call_clobbered (pi->name_mem_tag, ESCAPE_IS_GLOBAL);
-         MTAG_GLOBAL (pi->name_mem_tag) = true;
-       }
-      
-      if ((pi->pt_global_mem || pi->pt_anything) 
-         && pi->memory_tag_needed
-         && tag)
-       {
-         mark_call_clobbered (tag, ESCAPE_IS_GLOBAL);
-         MTAG_GLOBAL (tag) = true;
-       }
-    }
-
-  /* If a pt_anything pointer escaped we need to mark all addressable
-     variables call clobbered.  */
-  if (any_pt_anything)
-    {
-      bitmap_iterator bi;
-      unsigned int j;
-
-      EXECUTE_IF_SET_IN_BITMAP (gimple_addressable_vars (cfun), 0, j, bi)
-       {
-         tree var = referenced_var (j);
-         if (!unmodifiable_var_p (var))
-           mark_call_clobbered (var, pt_anything_mask);
-       }
-    }
-}
-
-/* Compute which variables need to be marked call clobbered because
-   their tag is call clobbered, and which tags need to be marked
-   global because they contain global variables.  */
-
-static void
-compute_call_clobbered (struct alias_info *ai)
-{
-  VEC (tree, heap) *worklist = NULL;
-  VEC (int,heap) *worklist2 = NULL;
-  bitmap on_worklist;
-
-  timevar_push (TV_CALL_CLOBBER);
-  on_worklist = BITMAP_ALLOC (NULL);
-    
-  set_initial_properties (ai);
-  init_transitive_clobber_worklist (&worklist, &worklist2, on_worklist);
-  while (VEC_length (tree, worklist) != 0)
-    {
-      tree curr = VEC_pop (tree, worklist);
-      int reason = VEC_pop (int, worklist2);
-
-      bitmap_clear_bit (on_worklist, DECL_UID (curr));
-      mark_call_clobbered (curr, reason);
-      mark_aliases_call_clobbered (curr, &worklist, &worklist2, on_worklist);
-    }
-  VEC_free (tree, heap, worklist);
-  VEC_free (int, heap, worklist2);
-  BITMAP_FREE (on_worklist);
-  compute_tag_properties ();
-  timevar_pop (TV_CALL_CLOBBER);
-}
-
-
-/* Dump memory partition information to FILE.  */
-
-static void
-dump_memory_partitions (FILE *file)
-{
-  unsigned i, npart;
-  unsigned long nsyms;
-  tree mpt;
-
-  fprintf (file, "\nMemory partitions\n\n");
-  for (i = 0, npart = 0, nsyms = 0;
-       VEC_iterate (tree, gimple_ssa_operands (cfun)->mpt_table, i, mpt);
-       i++)
-    {
-      if (mpt)
-       {
-         bitmap syms = MPT_SYMBOLS (mpt);
-         unsigned long n = (syms) ? bitmap_count_bits (syms) : 0;
-
-         fprintf (file, "#%u: ", i);
-         print_generic_expr (file, mpt, 0);
-         fprintf (file, ": %lu elements: ", n);
-         dump_decl_set (file, syms);
-         npart++;
-         nsyms += n;
-       }
-    }
-
-  fprintf (file, "\n%u memory partitions holding %lu symbols\n", npart, nsyms);
-}
-
-
-/* Dump memory partition information to stderr.  */
-
-void
-debug_memory_partitions (void)
-{
-  dump_memory_partitions (stderr);
-}
-
-
-/* Return true if memory partitioning is required given the memory
-   reference estimates in STATS.  */
-
-static inline bool
-need_to_partition_p (struct mem_ref_stats_d *stats)
-{
-  long num_vops = stats->num_vuses + stats->num_vdefs;
-  long avg_vops = CEIL (num_vops, stats->num_mem_stmts);
-  return (num_vops > (long) MAX_ALIASED_VOPS
-          && avg_vops > (long) AVG_ALIASED_VOPS);
-}
-
-
-/* Count the actual number of virtual operators in CFUN.  Note that
-   this is only meaningful after virtual operands have been populated,
-   so it should be invoked at the end of compute_may_aliases.
-
-   The number of virtual operators are stored in *NUM_VDEFS_P and
-   *NUM_VUSES_P, the number of partitioned symbols in
-   *NUM_PARTITIONED_P and the number of unpartitioned symbols in
-   *NUM_UNPARTITIONED_P.
-
-   If any of these pointers is NULL the corresponding count is not
-   computed.  */
-
-static void
-count_mem_refs (long *num_vuses_p, long *num_vdefs_p,
-               long *num_partitioned_p, long *num_unpartitioned_p)
-{
-  gimple_stmt_iterator gsi;
-  basic_block bb;
-  long num_vdefs, num_vuses, num_partitioned, num_unpartitioned;
-  referenced_var_iterator rvi;
-  tree sym;
-
-  num_vuses = num_vdefs = num_partitioned = num_unpartitioned = 0;
-
-  if (num_vuses_p || num_vdefs_p)
-    FOR_EACH_BB (bb)
-      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
-       {
-         gimple stmt = gsi_stmt (gsi);
-         if (gimple_references_memory_p (stmt))
-           {
-             num_vuses += NUM_SSA_OPERANDS (stmt, SSA_OP_VUSE);
-             num_vdefs += NUM_SSA_OPERANDS (stmt, SSA_OP_VDEF);
-           }
-       }
-
-  if (num_partitioned_p || num_unpartitioned_p)
-    FOR_EACH_REFERENCED_VAR (sym, rvi)
-      {
-       if (is_gimple_reg (sym))
-         continue;
-
-       if (memory_partition (sym))
-         num_partitioned++;
-       else
-         num_unpartitioned++;
-      }
-
-  if (num_vdefs_p)
-    *num_vdefs_p = num_vdefs;
-
-  if (num_vuses_p)
-    *num_vuses_p = num_vuses;
-
-  if (num_partitioned_p)
-    *num_partitioned_p = num_partitioned;
-
-  if (num_unpartitioned_p)
-    *num_unpartitioned_p = num_unpartitioned;
-}
-
-
-/* The list is sorted by increasing partitioning score (PSCORE).
-   This score is computed such that symbols with high scores are
-   those that are least likely to be partitioned.  Given a symbol
-   MP->VAR, PSCORE(S) is the result of the following weighted sum
-
-   PSCORE(S) =   FW * 64 + FR * 32
-              + DW * 16 + DR *  8 
-              + IW *  4 + IR *  2
-               + NO_ALIAS
-
-   where
-
-   FW          Execution frequency of writes to S
-   FR          Execution frequency of reads from S
-   DW          Number of direct writes to S
-   DR          Number of direct reads from S
-   IW          Number of indirect writes to S
-   IR          Number of indirect reads from S
-   NO_ALIAS    State of the NO_ALIAS* flags
-
-   The basic idea here is that symbols that are frequently
-   written-to in hot paths of the code are the last to be considered
-   for partitioning.  */
-
-static inline long
-mem_sym_score (mem_sym_stats_t mp)
-{
-  return mp->frequency_writes * 64 + mp->frequency_reads * 32
-         + mp->num_direct_writes * 16 + mp->num_direct_reads * 8
-        + mp->num_indirect_writes * 4 + mp->num_indirect_reads * 2
-        + var_ann (mp->var)->noalias_state;
-}
-
-
-/* Dump memory reference stats for function CFUN to FILE.  */
-
-void
-dump_mem_ref_stats (FILE *file)
-{
-  long actual_num_vuses, actual_num_vdefs;
-  long num_partitioned, num_unpartitioned;
-  struct mem_ref_stats_d *stats;
-  
-  stats = gimple_mem_ref_stats (cfun);
-
-  count_mem_refs (&actual_num_vuses, &actual_num_vdefs, &num_partitioned,
-                  &num_unpartitioned);
-
-  fprintf (file, "\nMemory reference statistics for %s\n\n", 
-          lang_hooks.decl_printable_name (current_function_decl, 2));
-
-  fprintf (file, "Number of memory statements:     %ld\n",
-           stats->num_mem_stmts);
-  fprintf (file, "Number of call sites:            %ld\n",
-          stats->num_call_sites);
-  fprintf (file, "Number of pure/const call sites: %ld\n",
-          stats->num_pure_const_call_sites);
-  fprintf (file, "Number of asm sites:             %ld\n",
-          stats->num_asm_sites);
-  fprintf (file, "Estimated number of loads:       %ld (%ld/stmt)\n",
-          stats->num_vuses,
-          (stats->num_mem_stmts)
-          ? CEIL (stats->num_vuses, stats->num_mem_stmts)
-          : 0);
-  fprintf (file, "Actual number of loads:          %ld (%ld/stmt)\n",
-          actual_num_vuses, 
-          (stats->num_mem_stmts)
-          ? CEIL (actual_num_vuses, stats->num_mem_stmts)
-          : 0);
-
-  if (actual_num_vuses > stats->num_vuses + (stats->num_vuses / 25))
-    fprintf (file, "\t(warning: estimation is lower by more than 25%%)\n");
-
-  fprintf (file, "Estimated number of stores:      %ld (%ld/stmt)\n",
-          stats->num_vdefs,
-          (stats->num_mem_stmts)
-          ? CEIL (stats->num_vdefs, stats->num_mem_stmts)
-          : 0);
-  fprintf (file, "Actual number of stores:         %ld (%ld/stmt)\n",
-          actual_num_vdefs, 
-          (stats->num_mem_stmts)
-          ? CEIL (actual_num_vdefs, stats->num_mem_stmts)
-          : 0);
-
-  if (actual_num_vdefs > stats->num_vdefs + (stats->num_vdefs / 25))
-    fprintf (file, "\t(warning: estimation is lower by more than 25%%)\n");
-
-  fprintf (file, "Partitioning thresholds:         MAX = %d   AVG = %d "
-           "(%sNEED TO PARTITION)\n", MAX_ALIASED_VOPS, AVG_ALIASED_VOPS,
-          stats->num_mem_stmts && need_to_partition_p (stats) ? "" : "NO ");
-  fprintf (file, "Number of partitioned symbols:   %ld\n", num_partitioned);
-  fprintf (file, "Number of unpartitioned symbols: %ld\n", num_unpartitioned);
-}
-
-
-/* Dump memory reference stats for function FN to stderr.  */
-
-void
-debug_mem_ref_stats (void)
-{
-  dump_mem_ref_stats (stderr);
-}
-
-
-/* Dump memory reference stats for variable VAR to FILE.  */
-
-static void
-dump_mem_sym_stats (FILE *file, tree var)
-{
-  mem_sym_stats_t stats = mem_sym_stats (cfun, var);
-
-  if (stats == NULL)
-    return;
-
-  fprintf (file, "read frequency: %6ld, write frequency: %6ld, "
-           "direct reads: %3ld, direct writes: %3ld, "
-          "indirect reads: %4ld, indirect writes: %4ld, symbol: ",
-          stats->frequency_reads, stats->frequency_writes,
-          stats->num_direct_reads, stats->num_direct_writes,
-          stats->num_indirect_reads, stats->num_indirect_writes);
-  print_generic_expr (file, stats->var, 0);
-  fprintf (file, ", tags: ");
-  dump_decl_set (file, stats->parent_tags);
-}
-
-
-/* Dump memory reference stats for variable VAR to stderr.  */
-
-void
-debug_mem_sym_stats (tree var)
-{
-  dump_mem_sym_stats (stderr, var);
-}
-
-/* Dump memory reference stats for variable VAR to FILE.  For use
-   of tree-dfa.c:dump_variable.  */
-
-void
-dump_mem_sym_stats_for_var (FILE *file, tree var)
-{
-  mem_sym_stats_t stats = mem_sym_stats (cfun, var);
-
-  if (stats == NULL)
-    return;
-
-  fprintf (file, ", score: %ld", mem_sym_score (stats));
-  fprintf (file, ", direct reads: %ld", stats->num_direct_reads);
-  fprintf (file, ", direct writes: %ld", stats->num_direct_writes);
-  fprintf (file, ", indirect reads: %ld", stats->num_indirect_reads);
-  fprintf (file, ", indirect writes: %ld", stats->num_indirect_writes);
-}
-
-/* Dump memory reference stats for all memory symbols to FILE.  */
-
-static void
-dump_all_mem_sym_stats (FILE *file)
-{
-  referenced_var_iterator rvi;
-  tree sym;
-
-  FOR_EACH_REFERENCED_VAR (sym, rvi)
-    {
-      if (is_gimple_reg (sym))
-       continue;
-
-      dump_mem_sym_stats (file, sym);
-    }
-}
-
-
-/* Dump memory reference stats for all memory symbols to stderr.  */
-
-void
-debug_all_mem_sym_stats (void)
-{
-  dump_all_mem_sym_stats (stderr);
-}
-
-
-/* Dump the MP_INFO array to FILE.  */
-
-static void
-dump_mp_info (FILE *file, VEC(mem_sym_stats_t,heap) *mp_info)
-{
-  unsigned i;
-  mem_sym_stats_t mp_p;
-
-  for (i = 0; VEC_iterate (mem_sym_stats_t, mp_info, i, mp_p); i++)
-    if (!mp_p->partitioned_p)
-      dump_mem_sym_stats (file, mp_p->var);
-}
-
-
-/* Dump the MP_INFO array to stderr.  */
-
-void
-debug_mp_info (VEC(mem_sym_stats_t,heap) *mp_info)
-{
-  dump_mp_info (stderr, mp_info);
-}
-
-
-/* Update memory reference stats for symbol VAR in statement STMT.
-   NUM_DIRECT_READS and NUM_DIRECT_WRITES specify the number of times
-   that VAR is read/written in STMT (indirect reads/writes are not
-   recorded by this function, see compute_memory_partitions).  */
-
-void
-update_mem_sym_stats_from_stmt (tree var, gimple stmt, long num_direct_reads,
-                                long num_direct_writes)
-{
-  mem_sym_stats_t stats;
-
-  gcc_assert (num_direct_reads >= 0 && num_direct_writes >= 0);
-
-  stats = get_mem_sym_stats_for (var);
-
-  stats->num_direct_reads += num_direct_reads;
-  stats->frequency_reads += ((long) gimple_bb (stmt)->frequency
-                             * num_direct_reads);
-
-  stats->num_direct_writes += num_direct_writes;
-  stats->frequency_writes += ((long) gimple_bb (stmt)->frequency
-                              * num_direct_writes);
-}
-
-
-/* Given two MP_INFO entries MP1 and MP2, return -1 if MP1->VAR should
-   be partitioned before MP2->VAR, 0 if they are the same or 1 if
-   MP1->VAR should be partitioned after MP2->VAR.  */
-
-static inline int
-compare_mp_info_entries (mem_sym_stats_t mp1, mem_sym_stats_t mp2)
-{
-  long pscore1 = mem_sym_score (mp1);
-  long pscore2 = mem_sym_score (mp2);
-
-  if (pscore1 < pscore2)
-    return -1;
-  else if (pscore1 > pscore2)
-    return 1;
-  else
-    return DECL_UID (mp1->var) - DECL_UID (mp2->var);
-}
-
-
-/* Comparison routine for qsort.  The list is sorted by increasing
-   partitioning score (PSCORE).  This score is computed such that
-   symbols with high scores are those that are least likely to be
-   partitioned.  */
-
-static int
-mp_info_cmp (const void *p, const void *q)
-{
-  mem_sym_stats_t e1 = *((const mem_sym_stats_t *) p);
-  mem_sym_stats_t e2 = *((const mem_sym_stats_t *) q);
-  return compare_mp_info_entries (e1, e2);
-}
-
-
-/* Sort the array of reference counts used to compute memory partitions.
-   Elements are sorted in ascending order of execution frequency and 
-   descending order of virtual operators needed.  */
-
-static inline void
-sort_mp_info (VEC(mem_sym_stats_t,heap) *list)
-{
-  unsigned num = VEC_length (mem_sym_stats_t, list);
-
-  if (num < 2)
-    return;
-
-  if (num == 2)
-    {
-      if (compare_mp_info_entries (VEC_index (mem_sym_stats_t, list, 0),
-                                  VEC_index (mem_sym_stats_t, list, 1)) > 0)
-       {  
-         /* Swap elements if they are in the wrong order.  */
-         mem_sym_stats_t tmp = VEC_index (mem_sym_stats_t, list, 0);
-         VEC_replace (mem_sym_stats_t, list, 0,
-                      VEC_index (mem_sym_stats_t, list, 1));
-         VEC_replace (mem_sym_stats_t, list, 1, tmp);
-       }
-
-      return;
-    }
-
-  /* There are 3 or more elements, call qsort.  */
-  qsort (VEC_address (mem_sym_stats_t, list),
-         VEC_length (mem_sym_stats_t, list), 
-        sizeof (mem_sym_stats_t),
-        mp_info_cmp);
-}
-
-
-/* Return the memory partition tag (MPT) associated with memory
-   symbol SYM.  */
-
-static tree
-get_mpt_for (tree sym)
-{
-  tree mpt;
-
-  /* Don't create a new tag unnecessarily.  */
-  mpt = memory_partition (sym);
-  if (mpt == NULL_TREE)
-    {
-      mpt = create_tag_raw (MEMORY_PARTITION_TAG, TREE_TYPE (sym), "MPT");
-      TREE_ADDRESSABLE (mpt) = 0;
-      add_referenced_var (mpt);
-      VEC_safe_push (tree, heap, gimple_ssa_operands (cfun)->mpt_table, mpt);
-      gcc_assert (MPT_SYMBOLS (mpt) == NULL);
-      set_memory_partition (sym, mpt);
-    }
-
-  return mpt;
-}
-
-
-/* Add MP_P->VAR to a memory partition and return the partition.  */
-
-static tree
-find_partition_for (mem_sym_stats_t mp_p)
-{
-  unsigned i;
-  VEC(tree,heap) *mpt_table;
-  tree mpt;
-
-  mpt_table = gimple_ssa_operands (cfun)->mpt_table;
-  mpt = NULL_TREE;
-
-  /* Find an existing partition for MP_P->VAR.  */
-  for (i = 0; VEC_iterate (tree, mpt_table, i, mpt); i++)
-    {
-      mem_sym_stats_t mpt_stats;
-
-      /* If MPT does not have any symbols yet, use it.  */
-      if (MPT_SYMBOLS (mpt) == NULL)
-       break;
-
-      /* Otherwise, see if MPT has common parent tags with MP_P->VAR,
-        but avoid grouping clobbered variables with non-clobbered
-        variables (otherwise, this tends to creates a single memory
-        partition because other call-clobbered variables may have
-        common parent tags with non-clobbered ones).  */
-      mpt_stats = get_mem_sym_stats_for (mpt);
-      if (mp_p->parent_tags
-         && mpt_stats->parent_tags
-         && is_call_clobbered (mpt) == is_call_clobbered (mp_p->var)
-         && bitmap_intersect_p (mpt_stats->parent_tags, mp_p->parent_tags))
-       break;
-
-      /* If no common parent tags are found, see if both MPT and
-        MP_P->VAR are call-clobbered.  */
-      if (is_call_clobbered (mpt) && is_call_clobbered (mp_p->var))
-       break;
-    }
-
-  if (mpt == NULL_TREE)
-    mpt = get_mpt_for (mp_p->var);
-  else
-    set_memory_partition (mp_p->var, mpt);
-
-  mp_p->partitioned_p = true;
-
-  mark_sym_for_renaming (mp_p->var);
-  mark_sym_for_renaming (mpt);
-
-  return mpt;
-}
-
-
-/* Rewrite the alias set for TAG to use the newly created partitions.
-   If TAG is NULL, rewrite the set of call-clobbered variables.
-   NEW_ALIASES is a scratch bitmap to build the new set of aliases for
-   TAG.  */
-
-static void
-rewrite_alias_set_for (tree tag, bitmap new_aliases)
-{
-  bitmap_iterator bi;
-  unsigned i;
-  tree mpt, sym;
-
-  EXECUTE_IF_SET_IN_BITMAP (MTAG_ALIASES (tag), 0, i, bi)
-    {
-      sym = referenced_var (i);
-      mpt = memory_partition (sym);
-      if (mpt)
-       bitmap_set_bit (new_aliases, DECL_UID (mpt));
-      else
-       bitmap_set_bit (new_aliases, DECL_UID (sym));
-    }
-
-  /* Rebuild the may-alias array for TAG.  */
-  bitmap_copy (MTAG_ALIASES (tag), new_aliases);
-}
-
-
-/* Determine how many virtual operands can be saved by partitioning
-   MP_P->VAR into MPT.  When a symbol S is thrown inside a partition
-   P, every virtual operand that used to reference S will now
-   reference P.  Whether it reduces the number of virtual operands
-   depends on:
-
-   1- Direct references to S are never saved.  Instead of the virtual
-      operand to S, we will now have a virtual operand to P.
-
-   2- Indirect references to S are reduced only for those memory tags
-      holding S that already had other symbols partitioned into P.
-      For instance, if a memory tag T has the alias set { a b S c },
-      the first time we partition S into P, the alias set will become
-      { a b P c }, so no virtual operands will be saved. However, if
-      we now partition symbol 'c' into P, then the alias set for T
-      will become { a b P }, so we will be saving one virtual operand
-      for every indirect reference to 'c'.
-
-   3- Is S is call-clobbered, we save as many virtual operands as
-      call/asm sites exist in the code, but only if other
-      call-clobbered symbols have been grouped into P.  The first
-      call-clobbered symbol that we group does not produce any
-      savings.
-
-   MEM_REF_STATS points to CFUN's memory reference information.  */
-
-static void
-estimate_vop_reduction (struct mem_ref_stats_d *mem_ref_stats,
-                        mem_sym_stats_t mp_p, tree mpt)
-{
-  unsigned i;
-  bitmap_iterator bi;
-  mem_sym_stats_t mpt_stats;
-
-  /* We should only get symbols with indirect references here.  */
-  gcc_assert (mp_p->num_indirect_reads > 0 || mp_p->num_indirect_writes > 0);
-
-  /* Note that the only statistics we keep for MPT is the set of
-     parent tags to know which memory tags have had alias members
-     partitioned, and the indicator has_call_clobbered_vars.
-     Reference counts are not important for MPT.  */
-  mpt_stats = get_mem_sym_stats_for (mpt);
-
-  /* Traverse all the parent tags for MP_P->VAR.  For every tag T, if
-     partition P is already grouping aliases of T, then reduce the
-     number of virtual operands by the number of direct references
-     to T.  */
-  if (mp_p->parent_tags)
-    {
-      if (mpt_stats->parent_tags == NULL)
-       mpt_stats->parent_tags = BITMAP_ALLOC (&alias_bitmap_obstack);
-
-      EXECUTE_IF_SET_IN_BITMAP (mp_p->parent_tags, 0, i, bi)
-       {
-         if (bitmap_bit_p (mpt_stats->parent_tags, i))
-           {
-             /* Partition MPT is already partitioning symbols in the
-                alias set for TAG.  This means that we are now saving
-                1 virtual operand for every direct reference to TAG.  */
-             tree tag = referenced_var (i);
-             mem_sym_stats_t tag_stats = mem_sym_stats (cfun, tag);
-             mem_ref_stats->num_vuses -= tag_stats->num_direct_reads;
-             mem_ref_stats->num_vdefs -= tag_stats->num_direct_writes;
-           }
-         else
-           {
-             /* This is the first symbol in tag I's alias set that is
-                being grouped under MPT.  We will not save any
-                virtual operands this time, but record that MPT is
-                grouping a symbol from TAG's alias set so that the
-                next time we get the savings.  */
-             bitmap_set_bit (mpt_stats->parent_tags, i);
-           }
-       }
-    }
-
-  /* If MP_P->VAR is call-clobbered, and MPT is already grouping
-     call-clobbered symbols, then we will save as many virtual
-     operands as asm/call sites there are.  */
-  if (is_call_clobbered (mp_p->var))
-    {
-      if (mpt_stats->has_call_clobbered_vars)
-       mem_ref_stats->num_vdefs -= mem_ref_stats->num_call_sites
-                                   + mem_ref_stats->num_asm_sites;
-      else
-       mpt_stats->has_call_clobbered_vars = true;
-    }
-}
-
-
-/* Helper for compute_memory_partitions.  Transfer reference counts
-   from pointers to their pointed-to sets.  Counters for pointers were
-   computed by update_alias_info.  MEM_REF_STATS points to CFUN's
-   memory reference information.  */
-
-static void
-update_reference_counts (struct mem_ref_stats_d *mem_ref_stats)
-{
-  unsigned i;
-  bitmap_iterator bi;
-  mem_sym_stats_t sym_stats;
-
-  for (i = 1; i < num_ssa_names; i++)
-    {
-      tree ptr;
-      struct ptr_info_def *pi;
-
-      ptr = ssa_name (i);
-      if (ptr
-         && POINTER_TYPE_P (TREE_TYPE (ptr))
-         && (pi = SSA_NAME_PTR_INFO (ptr)) != NULL
-         && pi->memory_tag_needed)
-       {
-         unsigned j;
-         bitmap_iterator bj;
-         tree tag;
-         mem_sym_stats_t ptr_stats, tag_stats;
-
-         /* If PTR has flow-sensitive points-to information, use
-            PTR's name tag, otherwise use the symbol tag associated
-            with PTR's symbol.  */
-         if (pi->name_mem_tag)
-           tag = pi->name_mem_tag;
-         else
-           tag = symbol_mem_tag (SSA_NAME_VAR (ptr));
-
-         ptr_stats = get_mem_sym_stats_for (ptr);
-         tag_stats = get_mem_sym_stats_for (tag);
-
-         /* TAG has as many direct references as dereferences we
-            found for its parent pointer.  */
-         tag_stats->num_direct_reads += ptr_stats->num_direct_reads;
-         tag_stats->num_direct_writes += ptr_stats->num_direct_writes;
-
-         /* All the dereferences of pointer PTR are considered direct
-            references to PTR's memory tag (TAG).  In turn,
-            references to TAG will become virtual operands for every
-            symbol in TAG's alias set.  So, for every symbol ALIAS in
-            TAG's alias set, add as many indirect references to ALIAS
-            as direct references there are for TAG.  */
-         if (MTAG_ALIASES (tag))
-           EXECUTE_IF_SET_IN_BITMAP (MTAG_ALIASES (tag), 0, j, bj)
-             {
-               tree alias = referenced_var (j);
-               sym_stats = get_mem_sym_stats_for (alias);
-
-               /* All the direct references to TAG are indirect references
-                  to ALIAS.  */
-               sym_stats->num_indirect_reads += ptr_stats->num_direct_reads;
-               sym_stats->num_indirect_writes += ptr_stats->num_direct_writes;
-               sym_stats->frequency_reads += ptr_stats->frequency_reads;
-               sym_stats->frequency_writes += ptr_stats->frequency_writes;
-
-               /* Indicate that TAG is one of ALIAS's parent tags.  */
-               if (sym_stats->parent_tags == NULL)
-                 sym_stats->parent_tags = BITMAP_ALLOC (&alias_bitmap_obstack);
-               bitmap_set_bit (sym_stats->parent_tags, DECL_UID (tag));
-             }
-       }
-    }
-
-  /* Call-clobbered symbols are indirectly written at every
-     call/asm site.  */
-  EXECUTE_IF_SET_IN_BITMAP (gimple_call_clobbered_vars (cfun), 0, i, bi)
-    {
-      tree sym = referenced_var (i);
-      sym_stats = get_mem_sym_stats_for (sym);
-      sym_stats->num_indirect_writes += mem_ref_stats->num_call_sites
-                                       + mem_ref_stats->num_asm_sites;
-    }
-
-  /* Addressable symbols are indirectly written at some ASM sites.
-     Since only ASM sites that clobber memory actually affect
-     addressable symbols, this is an over-estimation.  */
-  EXECUTE_IF_SET_IN_BITMAP (gimple_addressable_vars (cfun), 0, i, bi)
-    {
-      tree sym = referenced_var (i);
-      sym_stats = get_mem_sym_stats_for (sym);
-      sym_stats->num_indirect_writes += mem_ref_stats->num_asm_sites;
-    }
-}
-
-
-/* Helper for compute_memory_partitions.  Add all memory symbols to
-   *MP_INFO_P and compute the initial estimate for the total number of
-   virtual operands needed.  MEM_REF_STATS points to CFUN's memory
-   reference information.  On exit, *TAGS_P will contain the list of
-   memory tags whose alias set need to be rewritten after
-   partitioning.  */
-
-static void
-build_mp_info (struct mem_ref_stats_d *mem_ref_stats,
-               VEC(mem_sym_stats_t,heap) **mp_info_p,
-              VEC(tree,heap) **tags_p)
-{
-  tree var;
-  referenced_var_iterator rvi;
-
-  FOR_EACH_REFERENCED_VAR (var, rvi)
-    {
-      mem_sym_stats_t sym_stats;
-      tree old_mpt;
-
-      /* We are only interested in memory symbols other than MPTs.  */
-      if (is_gimple_reg (var) || TREE_CODE (var) == MEMORY_PARTITION_TAG)
-       continue;
-
-      /* Collect memory tags into the TAGS array so that we can
-        rewrite their alias sets after partitioning.  */
-      if (MTAG_P (var) && MTAG_ALIASES (var))
-       VEC_safe_push (tree, heap, *tags_p, var);
-
-      /* Since we are going to re-compute partitions, any symbols that
-        used to belong to a partition must be detached from it and
-        marked for renaming.  */
-      if ((old_mpt = memory_partition (var)) != NULL)
-       {
-         mark_sym_for_renaming (old_mpt);
-         set_memory_partition (var, NULL_TREE);
-         mark_sym_for_renaming (var);
-       }
-
-      sym_stats = get_mem_sym_stats_for (var);
-
-      /* Add VAR's reference info to MP_INFO.  Note that the only
-        symbols that make sense to partition are those that have
-        indirect references.  If a symbol S is always directly
-        referenced, partitioning it will not reduce the number of
-        virtual operators.  The only symbols that are profitable to
-        partition are those that belong to alias sets and/or are
-        call-clobbered.  */
-      if (sym_stats->num_indirect_reads > 0
-         || sym_stats->num_indirect_writes > 0)
-       VEC_safe_push (mem_sym_stats_t, heap, *mp_info_p, sym_stats);
-
-      /* Update the number of estimated VOPS.  Note that direct
-        references to memory tags are always counted as indirect
-        references to their alias set members, so if a memory tag has
-        aliases, do not count its direct references to avoid double
-        accounting.  */
-      if (!MTAG_P (var) || !MTAG_ALIASES (var))
-       {
-         mem_ref_stats->num_vuses += sym_stats->num_direct_reads;
-         mem_ref_stats->num_vdefs += sym_stats->num_direct_writes;
-       }
-
-      mem_ref_stats->num_vuses += sym_stats->num_indirect_reads;
-      mem_ref_stats->num_vdefs += sym_stats->num_indirect_writes;
-    }
-}
-
-
-/* Compute memory partitions.  A memory partition (MPT) is an
-   arbitrary grouping of memory symbols, such that references to one
-   member of the group is considered a reference to all the members of
-   the group.
-   
-   As opposed to alias sets in memory tags, the grouping into
-   partitions is completely arbitrary and only done to reduce the
-   number of virtual operands.  The only rule that needs to be
-   observed when creating memory partitions is that given two memory
-   partitions MPT.i and MPT.j, they must not contain symbols in
-   common.
-
-   Memory partitions are used when putting the program into Memory-SSA
-   form.  In particular, in Memory-SSA PHI nodes are not computed for
-   individual memory symbols.  They are computed for memory
-   partitions.  This reduces the amount of PHI nodes in the SSA graph
-   at the expense of precision (i.e., it makes unrelated stores affect
-   each other).
-   
-   However, it is possible to increase precision by changing this
-   partitioning scheme.  For instance, if the partitioning scheme is
-   such that get_mpt_for is the identity function (that is,
-   get_mpt_for (s) = s), this will result in ultimate precision at the
-   expense of huge SSA webs.
-
-   At the other extreme, a partitioning scheme that groups all the
-   symbols in the same set results in minimal SSA webs and almost
-   total loss of precision.
-
-   There partitioning heuristic uses three parameters to decide the
-   order in which symbols are processed.  The list of symbols is
-   sorted so that symbols that are more likely to be partitioned are
-   near the top of the list:
-
-   - Execution frequency.  If a memory references is in a frequently
-     executed code path, grouping it into a partition may block useful
-     transformations and cause sub-optimal code generation.  So, the
-     partition heuristic tries to avoid grouping symbols with high
-     execution frequency scores.  Execution frequency is taken
-     directly from the basic blocks where every reference is made (see
-     update_mem_sym_stats_from_stmt), which in turn uses the
-     profile guided machinery, so if the program is compiled with PGO
-     enabled, more accurate partitioning decisions will be made.
-
-   - Number of references.  Symbols with few references in the code,
-     are partitioned before symbols with many references.
-
-   - NO_ALIAS attributes.  Symbols with any of the NO_ALIAS*
-     attributes are partitioned after symbols marked MAY_ALIAS.
-
-   Once the list is sorted, the partitioning proceeds as follows:
-
-   1- For every symbol S in MP_INFO, create a new memory partition MP,
-      if necessary.  To avoid memory partitions that contain symbols
-      from non-conflicting alias sets, memory partitions are
-      associated to the memory tag that holds S in its alias set.  So,
-      when looking for a memory partition for S, the memory partition
-      associated with one of the memory tags holding S is chosen.  If
-      none exists, a new one is created.
-
-   2- Add S to memory partition MP.
-
-   3- Reduce by 1 the number of VOPS for every memory tag holding S.
-
-   4- If the total number of VOPS is less than MAX_ALIASED_VOPS or the
-      average number of VOPS per statement is less than
-      AVG_ALIASED_VOPS, stop.  Otherwise, go to the next symbol in the
-      list.  */
-
-static void
-compute_memory_partitions (void)
-{
-  tree tag;
-  unsigned i;
-  mem_sym_stats_t mp_p;
-  VEC(mem_sym_stats_t,heap) *mp_info;
-  bitmap new_aliases;
-  VEC(tree,heap) *tags;
-  struct mem_ref_stats_d *mem_ref_stats;
-  int prev_max_aliased_vops;
-
-  mem_ref_stats = gimple_mem_ref_stats (cfun);
-  gcc_assert (mem_ref_stats->num_vuses == 0 && mem_ref_stats->num_vdefs == 0);
-
-  if (mem_ref_stats->num_mem_stmts == 0)
-    return;
-
-  timevar_push (TV_MEMORY_PARTITIONING);
-
-  mp_info = NULL;
-  tags = NULL;
-  prev_max_aliased_vops = MAX_ALIASED_VOPS;
-
-  /* Since we clearly cannot lower the number of virtual operators
-     below the total number of memory statements in the function, we
-     may need to adjust MAX_ALIASED_VOPS beforehand.  */
-  if (MAX_ALIASED_VOPS < mem_ref_stats->num_mem_stmts)
-    MAX_ALIASED_VOPS = mem_ref_stats->num_mem_stmts;
-
-  /* Update reference stats for all the pointed-to variables and
-     memory tags.  */
-  update_reference_counts (mem_ref_stats);
-
-  /* Add all the memory symbols to MP_INFO.  */
-  build_mp_info (mem_ref_stats, &mp_info, &tags);
-
-  /* No partitions required if we are below the threshold.  */
-  if (!need_to_partition_p (mem_ref_stats))
-    {
-      if (dump_file)
-       fprintf (dump_file, "\nMemory partitioning NOT NEEDED for %s\n",
-                get_name (current_function_decl));
-      goto done;
-    }
-
-  /* Sort the MP_INFO array so that symbols that should be partitioned
-     first are near the top of the list.  */
-  sort_mp_info (mp_info);
-
-  if (dump_file)
-    {
-      fprintf (dump_file, "\nMemory partitioning NEEDED for %s\n\n",
-              get_name (current_function_decl));
-      fprintf (dump_file, "Memory symbol references before partitioning:\n");
-      dump_mp_info (dump_file, mp_info);
-    }
-
-  /* Create partitions for variables in MP_INFO until we have enough
-     to lower the total number of VOPS below MAX_ALIASED_VOPS or if
-     the average number of VOPS per statement is below
-     AVG_ALIASED_VOPS.  */
-  for (i = 0; VEC_iterate (mem_sym_stats_t, mp_info, i, mp_p); i++)
-    {
-      tree mpt;
-
-      /* If we are below the threshold, stop.  */
-      if (!need_to_partition_p (mem_ref_stats))
-       break;
-
-      mpt = find_partition_for (mp_p);
-      estimate_vop_reduction (mem_ref_stats, mp_p, mpt);
-    }
-
-  /* After partitions have been created, rewrite alias sets to use
-     them instead of the original symbols.  This way, if the alias set
-     was computed as { a b c d e f }, and the subset { b e f } was
-     grouped into partition MPT.3, then the new alias set for the tag
-     will be  { a c d MPT.3 }.
-     
-     Note that this is not strictly necessary.  The operand scanner
-     will always check if a symbol belongs to a partition when adding
-     virtual operands.  However, by reducing the size of the alias
-     sets to be scanned, the work needed inside the operand scanner is
-     significantly reduced.  */
-  new_aliases = BITMAP_ALLOC (&alias_bitmap_obstack);
-
-  for (i = 0; VEC_iterate (tree, tags, i, tag); i++)
-    {
-      rewrite_alias_set_for (tag, new_aliases);
-      bitmap_clear (new_aliases);
-    }
-
-  BITMAP_FREE (new_aliases);
-
-  if (dump_file)
-    {
-      fprintf (dump_file, "\nMemory symbol references after partitioning:\n");
-      dump_mp_info (dump_file, mp_info);
-    }
-
-done:
-  /* Free allocated memory.  */
-  VEC_free (mem_sym_stats_t, heap, mp_info);
-  VEC_free (tree, heap, tags);
-
-  MAX_ALIASED_VOPS = prev_max_aliased_vops;
-
-  timevar_pop (TV_MEMORY_PARTITIONING);
-}
-
-/* Compute may-alias information for every variable referenced in function
-   FNDECL.
-
-   Alias analysis proceeds in 3 main phases:
-
-   1- Points-to and escape analysis.
-
-   This phase walks the use-def chains in the SSA web looking for three
-   things:
-
-       * Assignments of the form P_i = &VAR
-       * Assignments of the form P_i = malloc()
-       * Pointers and ADDR_EXPR that escape the current function.
-
-   The concept of 'escaping' is the same one used in the Java world.  When
-   a pointer or an ADDR_EXPR escapes, it means that it has been exposed
-   outside of the current function.  So, assignment to global variables,
-   function arguments and returning a pointer are all escape sites, as are
-   conversions between pointers and integers.
-
-   This is where we are currently limited.  Since not everything is renamed
-   into SSA, we lose track of escape properties when a pointer is stashed
-   inside a field in a structure, for instance.  In those cases, we are
-   assuming that the pointer does escape.
-
-   We use escape analysis to determine whether a variable is
-   call-clobbered.  Simply put, if an ADDR_EXPR escapes, then the variable
-   is call-clobbered.  If a pointer P_i escapes, then all the variables
-   pointed-to by P_i (and its memory tag) also escape.
-
-   2- Compute flow-sensitive aliases
-
-   We have two classes of memory tags.  Memory tags associated with the
-   pointed-to data type of the pointers in the program.  These tags are
-   called "symbol memory tag" (SMT).  The other class are those associated
-   with SSA_NAMEs, called "name memory tag" (NMT). The basic idea is that
-   when adding operands for an INDIRECT_REF *P_i, we will first check
-   whether P_i has a name tag, if it does we use it, because that will have
-   more precise aliasing information.  Otherwise, we use the standard symbol
-   tag.
-
-   In this phase, we go through all the pointers we found in points-to
-   analysis and create alias sets for the name memory tags associated with
-   each pointer P_i.  If P_i escapes, we mark call-clobbered the variables
-   it points to and its tag.
-
-
-   3- Compute flow-insensitive aliases
-
-   This pass will compare the alias set of every symbol memory tag and
-   every addressable variable found in the program.  Given a symbol
-   memory tag SMT and an addressable variable V.  If the alias sets of
-   SMT and V conflict (as computed by may_alias_p), then V is marked
-   as an alias tag and added to the alias set of SMT.
-
-   For instance, consider the following function:
-
-           foo (int i)
-           {
-             int *p, a, b;
-           
-             if (i > 10)
-               p = &a;
-             else
-               p = &b;
-           
-             *p = 3;
-             a = b + 2;
-             return *p;
-           }
-
-   After aliasing analysis has finished, the symbol memory tag for pointer
-   'p' will have two aliases, namely variables 'a' and 'b'.  Every time
-   pointer 'p' is dereferenced, we want to mark the operation as a
-   potential reference to 'a' and 'b'.
-
-           foo (int i)
-           {
-             int *p, a, b;
-
-             if (i_2 > 10)
-               p_4 = &a;
-             else
-               p_6 = &b;
-             # p_1 = PHI <p_4(1), p_6(2)>;
-
-             # a_7 = VDEF <a_3>;
-             # b_8 = VDEF <b_5>;
-             *p_1 = 3;
-
-             # a_9 = VDEF <a_7>
-             # VUSE <b_8>
-             a_9 = b_8 + 2;
-
-             # VUSE <a_9>;
-             # VUSE <b_8>;
-             return *p_1;
-           }
-
-   In certain cases, the list of may aliases for a pointer may grow too
-   large.  This may cause an explosion in the number of virtual operands
-   inserted in the code.  Resulting in increased memory consumption and
-   compilation time.
-
-   When the number of virtual operands needed to represent aliased
-   loads and stores grows too large (configurable with option --param
-   max-aliased-vops and --param avg-aliased-vops), alias sets are
-   grouped to avoid severe compile-time slow downs and memory
-   consumption. See compute_memory_partitions.  */
-
-unsigned int
-compute_may_aliases (void)
-{
-  struct alias_info *ai;
-
-  timevar_push (TV_TREE_MAY_ALIAS);
-  
-  memset (&alias_stats, 0, sizeof (alias_stats));
-
-  /* Initialize aliasing information.  */
-  ai = init_alias_info ();
-
-  /* For each pointer P_i, determine the sets of variables that P_i may
-     point-to.  For every addressable variable V, determine whether the
-     address of V escapes the current function, making V call-clobbered
-     (i.e., whether &V is stored in a global variable or if its passed as a
-     function call argument).  */
-  compute_points_to_sets ();
-
-  /* Update various related attributes like escaped addresses,
-     pointer dereferences for loads and stores.  This is used
-     when creating name tags and alias sets.  */
-  update_alias_info (ai);
-
-  /* Collect all pointers and addressable variables, compute alias sets,
-     create memory tags for pointers and promote variables whose address is
-     not needed anymore.  */
-  setup_pointers_and_addressables (ai);
-
-  /* Compute type-based flow-insensitive aliasing for all the type
-     memory tags.  */
-  compute_flow_insensitive_aliasing (ai);
-
-  /* Compute flow-sensitive, points-to based aliasing for all the name
-     memory tags.  */
-  compute_flow_sensitive_aliasing (ai);
-  
-  /* Compute call clobbering information.  */
-  compute_call_clobbered (ai);
-
-  /* If the program makes no reference to global variables, but it
-     contains a mixture of pure and non-pure functions, then we need
-     to create use-def and def-def links between these functions to
-     avoid invalid transformations on them.  */
-  maybe_create_global_var ();
-
-  /* Compute memory partitions for every memory variable.  */
-  compute_memory_partitions ();
-
-  /* Remove partitions with no symbols.  Partitions may end up with an
-     empty MPT_SYMBOLS set if a previous round of alias analysis
-     needed to partition more symbols.  Since we don't need those
-     partitions anymore, remove them to free up the space.  */
-  {
-    tree mpt;
-    unsigned i;
-    VEC(tree,heap) *mpt_table;
-
-    mpt_table = gimple_ssa_operands (cfun)->mpt_table;
-    i = 0;
-    while (i < VEC_length (tree, mpt_table))
-      {
-       mpt = VEC_index (tree, mpt_table, i);
-       if (MPT_SYMBOLS (mpt) == NULL)
-         VEC_unordered_remove (tree, mpt_table, i);
-       else
-         i++;
-      }
-  }
-
-  /* Populate all virtual operands and newly promoted register operands.  */
-  {
-    gimple_stmt_iterator gsi;
-    basic_block bb;
-    FOR_EACH_BB (bb)
-      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
-       update_stmt_if_modified (gsi_stmt (gsi));
-  }
-
-  /* Debugging dumps.  */
-  if (dump_file)
-    {
-      dump_mem_ref_stats (dump_file);
-      dump_alias_info (dump_file);
-      dump_points_to_info (dump_file);
-
-      if (dump_flags & TDF_STATS)
-       dump_alias_stats (dump_file);
-
-      if (dump_flags & TDF_DETAILS)
-       dump_referenced_vars (dump_file);
-    }
-
-  /* Deallocate memory used by aliasing data structures.  */
-  delete_alias_info (ai);
-
-  if (need_ssa_update_p ())
-    update_ssa (TODO_update_ssa);
-
-  timevar_pop (TV_TREE_MAY_ALIAS);
-  
-  return 0;
-}
-
-/* Data structure used to count the number of dereferences to PTR
-   inside an expression.  */
-struct count_ptr_d
-{
-  tree ptr;
-  unsigned num_stores;
-  unsigned num_loads;
-};
-
-
-/* Helper for count_uses_and_derefs.  Called by walk_tree to look for
-   (ALIGN/MISALIGNED_)INDIRECT_REF nodes for the pointer passed in DATA.  */
-
-static tree
-count_ptr_derefs (tree *tp, int *walk_subtrees, void *data)
-{
-  struct walk_stmt_info *wi_p = (struct walk_stmt_info *) data;
-  struct count_ptr_d *count_p = (struct count_ptr_d *) wi_p->info;
-
-  /* Do not walk inside ADDR_EXPR nodes.  In the expression &ptr->fld,
-     pointer 'ptr' is *not* dereferenced, it is simply used to compute
-     the address of 'fld' as 'ptr + offsetof(fld)'.  */
-  if (TREE_CODE (*tp) == ADDR_EXPR)
-    {
-      *walk_subtrees = 0;
-      return NULL_TREE;
-    }
-
-  if (INDIRECT_REF_P (*tp) && TREE_OPERAND (*tp, 0) == count_p->ptr)
-    {
-      if (wi_p->is_lhs)
-       count_p->num_stores++;
-      else
-       count_p->num_loads++;
-    }
-
-  return NULL_TREE;
-}
-
-
-/* Count the number of direct and indirect uses for pointer PTR in
-   statement STMT.  The number of direct uses is stored in
-   *NUM_USES_P.  Indirect references are counted separately depending
-   on whether they are store or load operations.  The counts are
-   stored in *NUM_STORES_P and *NUM_LOADS_P.  */
-
-void
-count_uses_and_derefs (tree ptr, gimple stmt, unsigned *num_uses_p,
-                      unsigned *num_loads_p, unsigned *num_stores_p)
-{
-  ssa_op_iter i;
-  tree use;
-
-  *num_uses_p = 0;
-  *num_loads_p = 0;
-  *num_stores_p = 0;
-
-  /* Find out the total number of uses of PTR in STMT.  */
-  FOR_EACH_SSA_TREE_OPERAND (use, stmt, i, SSA_OP_USE)
-    if (use == ptr)
-      (*num_uses_p)++;
-
-  /* Now count the number of indirect references to PTR.  This is
-     truly awful, but we don't have much choice.  There are no parent
-     pointers inside INDIRECT_REFs, so an expression like
-     '*x_1 = foo (x_1, *x_1)' needs to be traversed piece by piece to
-     find all the indirect and direct uses of x_1 inside.  The only
-     shortcut we can take is the fact that GIMPLE only allows
-     INDIRECT_REFs inside the expressions below.  */
-  if (is_gimple_assign (stmt)
-      || gimple_code (stmt) == GIMPLE_RETURN
-      || gimple_code (stmt) == GIMPLE_ASM
-      || is_gimple_call (stmt))
-    {
-      struct walk_stmt_info wi;
-      struct count_ptr_d count;
-
-      count.ptr = ptr;
-      count.num_stores = 0;
-      count.num_loads = 0;
-
-      memset (&wi, 0, sizeof (wi));
-      wi.info = &count;
-      walk_gimple_op (stmt, count_ptr_derefs, &wi);
-
-      *num_stores_p = count.num_stores;
-      *num_loads_p = count.num_loads;
-    }
-
-  gcc_assert (*num_uses_p >= *num_loads_p + *num_stores_p);
-}
-
-/* Remove memory references stats for function FN.  */
-
-void
-delete_mem_ref_stats (struct function *fn)
-{
-  if (gimple_mem_ref_stats (fn)->mem_sym_stats)
-    {
-      free_alloc_pool (mem_sym_stats_pool);
-      pointer_map_destroy (gimple_mem_ref_stats (fn)->mem_sym_stats);
-    }
-  gimple_mem_ref_stats (fn)->mem_sym_stats = NULL;
-}
-
-
-/* Initialize memory reference stats.  */
-
-static void
-init_mem_ref_stats (void)
-{
-  struct mem_ref_stats_d *mem_ref_stats = gimple_mem_ref_stats (cfun);
-
-  mem_sym_stats_pool = create_alloc_pool ("Mem sym stats",
-                                         sizeof (struct mem_sym_stats_d),
-                                         100);
-  memset (mem_ref_stats, 0, sizeof (struct mem_ref_stats_d));
-  mem_ref_stats->mem_sym_stats = pointer_map_create ();
-}
-
-
-/* Helper for init_alias_info.  Reset existing aliasing information.  */
-
-static void
-reset_alias_info (void)
-{
-  referenced_var_iterator rvi;
-  tree var;
-  unsigned i;
-  bitmap active_nmts, all_nmts;
-
-  /* Clear the set of addressable variables.  We do not need to clear
-     the TREE_ADDRESSABLE bit on every symbol because we are going to
-     re-compute addressability here.  */
-  bitmap_clear (gimple_addressable_vars (cfun));
-
-  active_nmts = BITMAP_ALLOC (&alias_bitmap_obstack);
-  all_nmts = BITMAP_ALLOC (&alias_bitmap_obstack);
-
-  /* Clear flow-insensitive alias information from each symbol.  */
-  FOR_EACH_REFERENCED_VAR (var, rvi)
-    {
-      if (is_gimple_reg (var))
-       continue;
-
-      if (MTAG_P (var))
-       MTAG_ALIASES (var) = NULL;
-
-      /* Memory partition information will be computed from scratch.  */
-      if (TREE_CODE (var) == MEMORY_PARTITION_TAG)
-       MPT_SYMBOLS (var) = NULL;
-
-      /* Collect all the name tags to determine if we have any
-        orphaned that need to be removed from the IL.  A name tag
-        will be orphaned if it is not associated with any active SSA
-        name.  */
-      if (TREE_CODE (var) == NAME_MEMORY_TAG)
-       bitmap_set_bit (all_nmts, DECL_UID (var));
-
-      /* Since we are about to re-discover call-clobbered
-        variables, clear the call-clobbered flag.  */
-      clear_call_clobbered (var);
-    }
-
-  /* There should be no call-clobbered variable left.  */
-  gcc_assert (bitmap_empty_p (gimple_call_clobbered_vars (cfun)));
-
-  /* Clear the call-used variables.  */
-  bitmap_clear (gimple_call_used_vars (cfun));
-
-  /* Clear flow-sensitive points-to information from each SSA name.  */
-  for (i = 1; i < num_ssa_names; i++)
-    {
-      tree name = ssa_name (i);
-
-      if (!name || !POINTER_TYPE_P (TREE_TYPE (name)))
-       continue;
-
-      if (SSA_NAME_PTR_INFO (name))
-       {
-         struct ptr_info_def *pi = SSA_NAME_PTR_INFO (name);
-
-         /* Clear all the flags but keep the name tag to
-            avoid creating new temporaries unnecessarily.  If
-            this pointer is found to point to a subset or
-            superset of its former points-to set, then a new
-            tag will need to be created in create_name_tags.  */
-         pi->pt_anything = 0;
-         pi->pt_null = 0;
-         pi->value_escapes_p = 0;
-         pi->memory_tag_needed = 0;
-         pi->is_dereferenced = 0;
-         if (pi->pt_vars)
-           bitmap_clear (pi->pt_vars);
-
-         /* Add NAME's name tag to the set of active tags.  */
-         if (pi->name_mem_tag)
-           bitmap_set_bit (active_nmts, DECL_UID (pi->name_mem_tag));
-       }
-    }
-
-  /* Name memory tags that are no longer associated with an SSA name
-     are considered stale and should be removed from the IL.  All the
-     name tags that are in the set ALL_NMTS but not in ACTIVE_NMTS are
-     considered stale and marked for renaming.  */
-  bitmap_and_compl_into (all_nmts, active_nmts);
-  mark_set_for_renaming (all_nmts);
-
-  BITMAP_FREE (all_nmts);
-  BITMAP_FREE (active_nmts);
-}
-
-
-/* Initialize the data structures used for alias analysis.  */
-
-static struct alias_info *
-init_alias_info (void)
-{
-  struct alias_info *ai;
-  referenced_var_iterator rvi;
-  tree var;
-  static bool alias_bitmap_obstack_initialized;
-
-  ai = XCNEW (struct alias_info);
-  ai->ssa_names_visited = sbitmap_alloc (num_ssa_names);
-  sbitmap_zero (ai->ssa_names_visited);
-  ai->processed_ptrs = VEC_alloc (tree, heap, 50);
-  ai->dereferenced_ptrs = pointer_set_create ();
-
-  /* Clear out all memory reference stats.  */
-  init_mem_ref_stats ();
-
-  /* If aliases have been computed before, clear existing information.  */
-  if (gimple_aliases_computed_p (cfun))
-    reset_alias_info ();
-  else
-    {
-      /* If this is the first time we compute aliasing information,
-        every non-register symbol will need to be put into SSA form
-        (the initial SSA form only operates on GIMPLE registers).  */
-      FOR_EACH_REFERENCED_VAR (var, rvi)
-       if (!is_gimple_reg (var))
-         mark_sym_for_renaming (var);
-    }
-
-  /* Next time, we will need to reset alias information.  */
-  cfun->gimple_df->aliases_computed_p = true;
-  if (alias_bitmap_obstack_initialized)
-    bitmap_obstack_release (&alias_bitmap_obstack);    
-  bitmap_obstack_initialize (&alias_bitmap_obstack);
-  alias_bitmap_obstack_initialized = true;
-
-  return ai;
-}
-
-
-/* Deallocate memory used by alias analysis.  */
-
-static void
-delete_alias_info (struct alias_info *ai)
-{
-  size_t i;
-
-  sbitmap_free (ai->ssa_names_visited);
-
-  VEC_free (tree, heap, ai->processed_ptrs);
-
-  for (i = 0; i < ai->num_addressable_vars; i++)
-    free (ai->addressable_vars[i]);
-  free (ai->addressable_vars);
-  
-  for (i = 0; i < ai->num_pointers; i++)
-    free (ai->pointers[i]);
-  free (ai->pointers);
-
-  pointer_set_destroy (ai->dereferenced_ptrs);
-  free (ai);
-
-  delete_mem_ref_stats (cfun);
-  delete_points_to_sets ();
-}
-
-
-/* Used for hashing to identify pointer infos with identical
-   pt_vars bitmaps.  */
-
-static int
-eq_ptr_info (const void *p1, const void *p2)
-{
-  const struct ptr_info_def *n1 = (const struct ptr_info_def *) p1;
-  const struct ptr_info_def *n2 = (const struct ptr_info_def *) p2;
-  return bitmap_equal_p (n1->pt_vars, n2->pt_vars);
-}
-
-static hashval_t
-ptr_info_hash (const void *p)
-{
-  const struct ptr_info_def *n = (const struct ptr_info_def *) p;
-  return bitmap_hash (n->pt_vars);
-}
-
-
-/* Create name tags for all the pointers that have been dereferenced.
-   We only create a name tag for a pointer P if P is found to point to
-   a set of variables (so that we can alias them to *P) or if it is
-   the result of a call to malloc (which means that P cannot point to
-   anything else nor alias any other variable).
-
-   If two pointers P and Q point to the same set of variables, they
-   are assigned the same name tag.  */
-
-static void
-create_name_tags (void)
-{
-  size_t i;
-  VEC (tree, heap) *with_ptvars = NULL;
-  tree ptr;
-  htab_t ptr_hash;
-
-  /* Collect the list of pointers with a non-empty points to set.  */
-  for (i = 1; i < num_ssa_names; i++)
-    {
-      tree ptr = ssa_name (i);
-      struct ptr_info_def *pi;
-
-      if (!ptr
-         || !POINTER_TYPE_P (TREE_TYPE (ptr))
-         || !SSA_NAME_PTR_INFO (ptr))
-       continue;
-
-      pi = SSA_NAME_PTR_INFO (ptr);
-
-      if (pi->pt_anything || !pi->memory_tag_needed)
-       {
-         /* No name tags for pointers that have not been
-            dereferenced or point to an arbitrary location.  */
-         pi->name_mem_tag = NULL_TREE;
-         continue;
-       }
-
-      /* Set pt_anything on the pointers without pt_vars filled in so
-        that they are assigned a symbol tag.  */
-      if (pi->pt_vars && !bitmap_empty_p (pi->pt_vars))        
-       VEC_safe_push (tree, heap, with_ptvars, ptr);
-      else
-       set_pt_anything (ptr);
-    }
-  
-  /* If we didn't find any pointers with pt_vars set, we're done.  */
-  if (!with_ptvars)
-    return;
-
-  ptr_hash = htab_create (10, ptr_info_hash, eq_ptr_info, NULL);
-
-  /* Now go through the pointers with pt_vars, and find a name tag
-     with the same pt_vars as this pointer, or create one if one
-     doesn't exist.  */
-  for (i = 0; VEC_iterate (tree, with_ptvars, i, ptr); i++)
-    {
-      struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
-      tree old_name_tag = pi->name_mem_tag;
-      struct ptr_info_def **slot;
-      
-      /* If PTR points to a set of variables, check if we don't
-        have another pointer Q with the same points-to set before
-        creating a tag.  If so, use Q's tag instead of creating a
-        new one.
-        
-        This is important for not creating unnecessary symbols
-        and also for copy propagation.  If we ever need to
-        propagate PTR into Q or vice-versa, we would run into
-        problems if they both had different name tags because
-        they would have different SSA version numbers (which
-        would force us to take the name tags in and out of SSA).  */
-      slot = (struct ptr_info_def **) htab_find_slot (ptr_hash, pi, INSERT);
-      if (*slot)
-        pi->name_mem_tag = (*slot)->name_mem_tag;
-      else
-       {
-         *slot = pi;
-
-         /* If we didn't find a pointer with the same points-to set
-            as PTR, create a new name tag if needed.  */
-         if (pi->name_mem_tag == NULL_TREE)
-           pi->name_mem_tag = get_nmt_for (ptr);
-       }
-      
-      /* If the new name tag computed for PTR is different than
-        the old name tag that it used to have, then the old tag
-        needs to be removed from the IL, so we mark it for
-        renaming.  */
-      if (old_name_tag && old_name_tag != pi->name_mem_tag)
-       mark_sym_for_renaming (old_name_tag);
-
-      /* Inherit volatility from the pointed-to type.  */
-      TREE_THIS_VOLATILE (pi->name_mem_tag)
-       |= TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (ptr)));
-      
-      /* Mark the new name tag for renaming.  */
-      mark_sym_for_renaming (pi->name_mem_tag);
-    }
-
-  htab_delete (ptr_hash);
-
-  VEC_free (tree, heap, with_ptvars);
-}
-
-
-/* Union the alias set SET into the may-aliases for TAG.  */
-
-static void
-union_alias_set_into (tree tag, bitmap set)
-{
-  bitmap ma = MTAG_ALIASES (tag);
-  
-  if (bitmap_empty_p (set))
-    return;
-  
-  if (!ma)
-    ma = MTAG_ALIASES (tag) = BITMAP_ALLOC (&alias_bitmap_obstack);
-  bitmap_ior_into (ma, set);
-}
-
-
-/* For every pointer P_i in AI->PROCESSED_PTRS, create may-alias sets for
-   the name memory tag (NMT) associated with P_i.  If P_i escapes, then its
-   name tag and the variables it points-to are call-clobbered.  Finally, if
-   P_i escapes and we could not determine where it points to, then all the
-   variables in the same alias set as *P_i are marked call-clobbered.  This
-   is necessary because we must assume that P_i may take the address of any
-   variable in the same alias set.  */
-
-static void
-compute_flow_sensitive_aliasing (struct alias_info *ai)
-{
-  size_t i;
-  tree ptr;
-  
-  timevar_push (TV_FLOW_SENSITIVE);
-  
-  for (i = 0; VEC_iterate (tree, ai->processed_ptrs, i, ptr); i++)
-    {
-      if (!find_what_p_points_to (ptr))
-       set_pt_anything (ptr);
-    }
-
-  create_name_tags ();
-
-  for (i = 0; VEC_iterate (tree, ai->processed_ptrs, i, ptr); i++)
-    {
-      struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
-
-      /* Set up aliasing information for PTR's name memory tag (if it has
-        one).  Note that only pointers that have been dereferenced will
-        have a name memory tag.  */
-      if (pi->name_mem_tag && pi->pt_vars)
-       {
-         if (!bitmap_empty_p (pi->pt_vars))
-           union_alias_set_into (pi->name_mem_tag, pi->pt_vars);
-       }
-    }
-  timevar_pop (TV_FLOW_SENSITIVE);
-}
-
-
-/* Return TRUE if at least one symbol in TAG2's alias set is also
-   present in TAG1's alias set.  */
-
-static bool
-have_common_aliases_p (bitmap tag1aliases, bitmap tag2aliases)
-{
+/* Broad overview of how alias analysis on gimple works:
 
-  /* This is the old behavior of have_common_aliases_p, which is to
-     return false if both sets are empty, or one set is and the other
-     isn't.  */
-  if (tag1aliases == NULL || tag2aliases == NULL)
-    return false;
-
-  return bitmap_intersect_p (tag1aliases, tag2aliases);
-}
-
-/* Compute type-based alias sets.  Traverse all the pointers and
-   addressable variables found in setup_pointers_and_addressables.
-   
-   For every pointer P in AI->POINTERS and addressable variable V in
-   AI->ADDRESSABLE_VARS, add V to the may-alias sets of P's symbol
-   memory tag (SMT) if their alias sets conflict.  V is then marked as
-   an aliased symbol so that the operand scanner knows that statements
-   containing V have aliased operands.  */
-
-static void
-compute_flow_insensitive_aliasing (struct alias_info *ai)
-{
-  referenced_var_iterator rvi;
-  tree var;
-  size_t i;
-
-  timevar_push (TV_FLOW_INSENSITIVE);
-  /* For every pointer P, determine which addressable variables may alias
-     with P's symbol memory tag.  */
-  for (i = 0; i < ai->num_pointers; i++)
-    {
-      size_t j;
-      struct alias_map_d *p_map = ai->pointers[i];
-      tree tag = symbol_mem_tag (p_map->var);
-      tree var;
-
-      for (j = 0; j < ai->num_addressable_vars; j++)
-       {
-         struct alias_map_d *v_map;
-         var_ann_t v_ann;
-         
-         v_map = ai->addressable_vars[j];
-         var = v_map->var;
-         v_ann = var_ann (var);
-
-         /* We used to skip variables that have never been written to
-            if the memory tag has been never written to directly (or
-            either of them were call clobbered).  This is not enough
-            though, as this misses writes through the tags aliases.
-            So, for correctness we need to include any aliased
-            variable here.  */
-
-         if (may_alias_p (p_map->var, p_map->set, var, v_map->set, false))
-           {
-             /* Add VAR to TAG's may-aliases set.  */
-             add_may_alias (tag, var);
-           }
-       }
-    }
-
-  /* Since this analysis is based exclusively on symbols, it fails to
-     handle cases where two pointers P and Q have different memory
-     tags with conflicting alias set numbers but no aliased symbols in
-     common.
-
-     For example, suppose that we have two memory tags SMT.1 and SMT.2
-     such that
-     
-               may-aliases (SMT.1) = { a }
-               may-aliases (SMT.2) = { b }
-
-     and the alias set number of SMT.1 conflicts with that of SMT.2.
-     Since they don't have symbols in common, loads and stores from
-     SMT.1 and SMT.2 will seem independent of each other, which will
-     lead to the optimizers making invalid transformations (see
-     testsuite/gcc.c-torture/execute/pr15262-[12].c).
-
-     To avoid this problem, we do a final traversal of AI->POINTERS
-     looking for pairs of pointers that have no aliased symbols in
-     common and yet have conflicting alias set numbers.  */
-  for (i = 0; i < ai->num_pointers; i++)
-    {
-      size_t j;
-      struct alias_map_d *p_map1 = ai->pointers[i];
-      tree tag1 = symbol_mem_tag (p_map1->var);
-      bitmap may_aliases1 = MTAG_ALIASES (tag1);
-
-      for (j = 0; j < ai->num_pointers; j++)
-       {
-         struct alias_map_d *p_map2 = ai->pointers[j];
-         tree tag2 = symbol_mem_tag (p_map2->var);
-         bitmap may_aliases2 = may_aliases (tag2);
-
-         /* By convention tags don't alias themselves.  */
-         if (tag1 == tag2)
-           continue;
-
-         /* If the pointers may not point to each other, do nothing.  */
-         if (!may_alias_p (p_map1->var, p_map1->set, tag2, p_map2->set, true))
-           continue;
-
-         /* The two pointers may alias each other.  If they already have
-            symbols in common, do nothing.  */
-         if (have_common_aliases_p (may_aliases1, may_aliases2))
-           continue;
-
-         add_may_alias (tag1, tag2);
-       }
-    }
-
-  /* We have to add all HEAP variables to all SMTs aliases bitmaps.
-     As we don't know which effective type the HEAP will have we cannot
-     do better here and we need the conflicts with obfuscated pointers
-     (a simple (*(int[n] *)ptr)[i] will do, with ptr from a VLA array
-     allocation).  */
-  for (i = 0; i < ai->num_pointers; i++)
-    {
-      struct alias_map_d *p_map = ai->pointers[i];
-      tree tag = symbol_mem_tag (p_map->var);
-
-      FOR_EACH_REFERENCED_VAR (var, rvi)
-       {
-         if (var_ann (var)->is_heapvar)
-           add_may_alias (tag, var);
-       }
-    }
-
-  timevar_pop (TV_FLOW_INSENSITIVE);
-}
-
-
-/* Create a new alias set entry for VAR in AI->ADDRESSABLE_VARS.  */
-
-static void
-create_alias_map_for (tree var, struct alias_info *ai)
-{
-  struct alias_map_d *alias_map;
-  alias_map = XCNEW (struct alias_map_d);
-  alias_map->var = var;
-  alias_map->set = get_alias_set (var);
-  ai->addressable_vars[ai->num_addressable_vars++] = alias_map;
-}
-
-
-/* Update related alias information kept in AI.  This is used when
-   building name tags, alias sets and deciding grouping heuristics.
-   STMT is the statement to process.  This function also updates
-   ADDRESSABLE_VARS.  */
-
-static void
-update_alias_info_1 (gimple stmt, struct alias_info *ai)
-{
-  bitmap addr_taken;
-  use_operand_p use_p;
-  ssa_op_iter iter;
-  bool stmt_dereferences_ptr_p;
-  enum escape_type stmt_escape_type = is_escape_site (stmt);
-  struct mem_ref_stats_d *mem_ref_stats = gimple_mem_ref_stats (cfun);
-
-  stmt_dereferences_ptr_p = false;
-
-  if (stmt_escape_type == ESCAPE_TO_CALL
-      || stmt_escape_type == ESCAPE_TO_PURE_CONST)
-    {
-      mem_ref_stats->num_call_sites++;
-      if (stmt_escape_type == ESCAPE_TO_PURE_CONST)
-       mem_ref_stats->num_pure_const_call_sites++;
-    }
-  else if (stmt_escape_type == ESCAPE_TO_ASM)
-    mem_ref_stats->num_asm_sites++;
-
-  /* Mark all the variables whose address are taken by the statement.  */
-  addr_taken = gimple_addresses_taken (stmt);
-  if (addr_taken)
-    bitmap_ior_into (gimple_addressable_vars (cfun), addr_taken);
-
-  /* If we have a call or an assignment, see if the lhs contains
-     a local decl that requires not to be a gimple register.  */
-  if (gimple_code (stmt) == GIMPLE_ASSIGN
-      || gimple_code (stmt) == GIMPLE_CALL)
-    {
-      tree lhs = gimple_get_lhs (stmt);
-      /* A plain decl does not need it set.  */
-      if (lhs && handled_component_p (lhs))
-       {
-         tree var = get_base_address (lhs);
-         if (DECL_P (var)
-             /* We are not going to mess with RESULT_DECL anyway.  */
-             && TREE_CODE (var) != RESULT_DECL
-             && is_gimple_reg_type (TREE_TYPE (var)))
-           bitmap_set_bit (gimple_addressable_vars (cfun), DECL_UID (var));
-       }
-    }
-
-  /* Process each operand use.  For pointers, determine whether they
-     are dereferenced by the statement, or whether their value
-     escapes, etc.  */
-  FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_USE)
-    {
-      tree op, var;
-      var_ann_t v_ann;
-      struct ptr_info_def *pi;
-      unsigned num_uses, num_loads, num_stores;
-
-      op = USE_FROM_PTR (use_p);
-
-      /* If STMT is a PHI node, OP may be an ADDR_EXPR.  If so, add it
-        to the set of addressable variables.  */
-      if (TREE_CODE (op) == ADDR_EXPR)
-       {
-         bitmap addressable_vars = gimple_addressable_vars (cfun);
-
-         gcc_assert (gimple_code (stmt) == GIMPLE_PHI);
-         gcc_assert (addressable_vars);
-
-         /* PHI nodes don't have annotations for pinning the set
-            of addresses taken, so we collect them here.
-
-            FIXME, should we allow PHI nodes to have annotations
-            so that they can be treated like regular statements?
-            Currently, they are treated as second-class
-            statements.  */
-         add_to_addressable_set (TREE_OPERAND (op, 0), &addressable_vars);
-         continue;
-       }
-
-      /* Ignore constants (they may occur in PHI node arguments).  */
-      if (TREE_CODE (op) != SSA_NAME)
-       continue;
-
-      var = SSA_NAME_VAR (op);
-      v_ann = var_ann (var);
-
-      /* The base variable of an SSA name must be a GIMPLE register, and thus
-        it cannot be aliased.  */
-      gcc_assert (!may_be_aliased (var));
+   Statements clobbering or using memory are linked through the
+   virtual operand factored use-def chain.  The virtual operand
+   is unique per function, its symbol is accessible via gimple_vop (cfun).
+   Virtual operands are used for efficiently walking memory statements
+   in the gimple IL and are useful for things like value-numbering as
+   a generation count for memory references.
 
-      /* We are only interested in pointers.  */
-      if (!POINTER_TYPE_P (TREE_TYPE (op)))
-       continue;
-
-      pi = get_ptr_info (op);
-
-      /* Add OP to AI->PROCESSED_PTRS, if it's not there already.  */
-      if (!TEST_BIT (ai->ssa_names_visited, SSA_NAME_VERSION (op)))
-       {
-         SET_BIT (ai->ssa_names_visited, SSA_NAME_VERSION (op));
-         VEC_safe_push (tree, heap, ai->processed_ptrs, op);
-       }
-
-      /* If STMT is a PHI node, then it will not have pointer
-        dereferences and it will not be an escape point.  */
-      if (gimple_code (stmt) == GIMPLE_PHI)
-       continue;
+   SSA_NAME pointers may have associated points-to information
+   accessible via the SSA_NAME_PTR_INFO macro.  Flow-insensitive
+   points-to information is (re-)computed by the TODO_rebuild_alias
+   pass manager todo.  Points-to information is also used for more
+   precise tracking of call-clobbered and call-used variables and
+   related disambiguations.
 
-      /* Determine whether OP is a dereferenced pointer, and if STMT
-        is an escape point, whether OP escapes.  */
-      count_uses_and_derefs (op, stmt, &num_uses, &num_loads, &num_stores);
-
-      /* For directly dereferenced pointers we can apply
-        TBAA-pruning to their points-to set.  We may not count the
-        implicit dereferences &PTR->FLD here.  */
-      if (num_loads + num_stores > 0)
-       pi->is_dereferenced = 1;
-
-      /* Handle a corner case involving address expressions of the
-        form '&PTR->FLD'.  The problem with these expressions is that
-        they do not represent a dereference of PTR.  However, if some
-        other transformation propagates them into an INDIRECT_REF
-        expression, we end up with '*(&PTR->FLD)' which is folded
-        into 'PTR->FLD'.
-
-        So, if the original code had no other dereferences of PTR,
-        the aliaser will not create memory tags for it, and when
-        &PTR->FLD gets propagated to INDIRECT_REF expressions, the
-        memory operations will receive no VDEF/VUSE operands.
-
-        One solution would be to have count_uses_and_derefs consider
-        &PTR->FLD a dereference of PTR.  But that is wrong, since it
-        is not really a dereference but an offset calculation.
-
-        What we do here is to recognize these special ADDR_EXPR
-        nodes.  Since these expressions are never GIMPLE values (they
-        are not GIMPLE invariants), they can only appear on the RHS
-        of an assignment and their base address is always an
-        INDIRECT_REF expression.  */
-      if (is_gimple_assign (stmt)
-         && gimple_assign_rhs_code (stmt) == ADDR_EXPR
-         && !is_gimple_val (gimple_assign_rhs1 (stmt)))
-       {
-         /* If the RHS if of the form &PTR->FLD and PTR == OP, then
-            this represents a potential dereference of PTR.  */
-         tree rhs = gimple_assign_rhs1 (stmt);
-         tree base = get_base_address (TREE_OPERAND (rhs, 0));
-         if (TREE_CODE (base) == INDIRECT_REF
-             && TREE_OPERAND (base, 0) == op)
-           num_loads++;
-       }
+   This file contains functions for disambiguating memory references,
+   the so called alias-oracle and tools for walking of the gimple IL.
 
-      if (num_loads + num_stores > 0)
-       {
-         /* Mark OP as dereferenced.  In a subsequent pass,
-            dereferenced pointers that point to a set of
-            variables will be assigned a name tag to alias
-            all the variables OP points to.  */
-         pi->memory_tag_needed = 1;
+   The main alias-oracle entry-points are
 
-         /* ???  For always executed direct dereferences we can
-            apply TBAA-pruning to their escape set.  */
+   bool stmt_may_clobber_ref_p (gimple, tree)
 
-         /* Mark OP as being dereferenced.  */
-         pointer_set_insert (ai->dereferenced_ptrs, var);
+     This function queries if a statement may invalidate (parts of)
+     the memory designated by the reference tree argument.
 
-         /* Update the frequency estimate for all the dereferences of
-            pointer OP.  */
-         update_mem_sym_stats_from_stmt (op, stmt, num_loads, num_stores);
+   bool ref_maybe_used_by_stmt_p (gimple, tree)
 
-         /* Indicate that STMT contains pointer dereferences.  */
-         stmt_dereferences_ptr_p = true;
-       }
+     This function queries if a statement may need (parts of) the
+     memory designated by the reference tree argument.
 
-      if (stmt_escape_type != NO_ESCAPE && num_loads + num_stores < num_uses)
-       {
-         /* If STMT is an escape point and STMT contains at
-            least one direct use of OP, then the value of OP
-            escapes and so the pointed-to variables need to
-            be marked call-clobbered.  */
-         pi->value_escapes_p = 1;
-         pi->escape_mask |= stmt_escape_type;
-
-         /* If the statement makes a function call, assume
-            that pointer OP will be dereferenced in a store
-            operation inside the called function.  */
-         if (is_gimple_call (stmt)
-             || stmt_escape_type == ESCAPE_STORED_IN_GLOBAL)
-           {
-             pointer_set_insert (ai->dereferenced_ptrs, var);
-             pi->memory_tag_needed = 1;
-           }
-       }
-    }
+   There are variants of these functions that only handle the call
+   part of a statement, call_may_clobber_ref_p and ref_maybe_used_by_call_p.
+   Note that these do not disambiguate against a possible call lhs.
 
-  if (gimple_code (stmt) == GIMPLE_PHI)
-    return;
+   bool refs_may_alias_p (tree, tree)
 
-  /* Mark stored variables in STMT as being written to and update the
-     memory reference stats for all memory symbols referenced by STMT.  */
-  if (gimple_references_memory_p (stmt))
-    {
-      unsigned i;
-      bitmap_iterator bi;
-
-      mem_ref_stats->num_mem_stmts++;
-
-      /* Notice that we only update memory reference stats for symbols
-        loaded and stored by the statement if the statement does not
-        contain pointer dereferences and it is not a call/asm site.
-        This is to avoid double accounting problems when creating
-        memory partitions.  After computing points-to information,
-        pointer dereference statistics are used to update the
-        reference stats of the pointed-to variables, so here we
-        should only update direct references to symbols.
-
-        Indirect references are not updated here for two reasons: (1)
-        The first time we compute alias information, the sets
-        LOADED/STORED are empty for pointer dereferences, (2) After
-        partitioning, LOADED/STORED may have references to
-        partitions, not the original pointed-to variables.  So, if we
-        always counted LOADED/STORED here and during partitioning, we
-        would count many symbols more than once.
-
-        This does cause some imprecision when a statement has a
-        combination of direct symbol references and pointer
-        dereferences (e.g., MEMORY_VAR = *PTR) or if a call site has
-        memory symbols in its argument list, but these cases do not
-        occur so frequently as to constitute a serious problem.  */
-      if (!stmt_dereferences_ptr_p
-         && stmt_escape_type != ESCAPE_TO_CALL
-         && stmt_escape_type != ESCAPE_TO_PURE_CONST
-         && stmt_escape_type != ESCAPE_TO_ASM)
-       {
-         if (gimple_stored_syms (stmt))
-           EXECUTE_IF_SET_IN_BITMAP (gimple_stored_syms (stmt), 0, i, bi)
-             update_mem_sym_stats_from_stmt (referenced_var (i), stmt, 0, 1);
+     This function tries to disambiguate two reference trees.
 
-         if (gimple_loaded_syms (stmt))
-           EXECUTE_IF_SET_IN_BITMAP (gimple_loaded_syms (stmt), 0, i, bi)
-             update_mem_sym_stats_from_stmt (referenced_var (i), stmt, 1, 0);
-       }
-    }
-}
+   bool ptr_deref_may_alias_global_p (tree)
 
-/* Update various related attributes like escaped addresses,
-   pointer dereferences for loads and stores.  This is used
-   when creating name tags and alias sets.  */
+     This function queries if dereferencing a pointer variable may
+     alias global memory.
 
-static void
-update_alias_info (struct alias_info *ai)
-{
-  basic_block bb;
+   More low-level disambiguators are available and documented in
+   this file.  Low-level disambiguators dealing with points-to
+   information are in tree-ssa-structalias.c.  */
 
-  FOR_EACH_BB (bb)
-    {
-      gimple_stmt_iterator gsi;
-      gimple phi;
 
-      for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
-       {
-         phi = gsi_stmt (gsi);
-         if (is_gimple_reg (PHI_RESULT (phi)))
-           update_alias_info_1 (phi, ai);
-       }
+/* Query statistics for the different low-level disambiguators.
+   A high-level query may trigger multiple of them.  */
 
-      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
-       update_alias_info_1 (gsi_stmt (gsi), ai);
-    }
-}
+static struct {
+  unsigned HOST_WIDE_INT refs_may_alias_p_may_alias;
+  unsigned HOST_WIDE_INT refs_may_alias_p_no_alias;
+  unsigned HOST_WIDE_INT ref_maybe_used_by_call_p_may_alias;
+  unsigned HOST_WIDE_INT ref_maybe_used_by_call_p_no_alias;
+  unsigned HOST_WIDE_INT call_may_clobber_ref_p_may_alias;
+  unsigned HOST_WIDE_INT call_may_clobber_ref_p_no_alias;
+} alias_stats;
 
-/* Create memory tags for all the dereferenced pointers and build the
-   ADDRESSABLE_VARS and POINTERS arrays used for building the may-alias
-   sets.  Based on the address escape and points-to information collected
-   earlier, this pass will also clear the TREE_ADDRESSABLE flag from those
-   variables whose address is not needed anymore.  */
+void
+dump_alias_stats (FILE *s)
+{
+  fprintf (s, "\nAlias oracle query stats:\n");
+  fprintf (s, "  refs_may_alias_p: "
+          HOST_WIDE_INT_PRINT_DEC" disambiguations, "
+          HOST_WIDE_INT_PRINT_DEC" queries\n",
+          alias_stats.refs_may_alias_p_no_alias,
+          alias_stats.refs_may_alias_p_no_alias
+          + alias_stats.refs_may_alias_p_may_alias);
+  fprintf (s, "  ref_maybe_used_by_call_p: "
+          HOST_WIDE_INT_PRINT_DEC" disambiguations, "
+          HOST_WIDE_INT_PRINT_DEC" queries\n",
+          alias_stats.ref_maybe_used_by_call_p_no_alias,
+          alias_stats.refs_may_alias_p_no_alias
+          + alias_stats.ref_maybe_used_by_call_p_may_alias);
+  fprintf (s, "  call_may_clobber_ref_p: "
+          HOST_WIDE_INT_PRINT_DEC" disambiguations, "
+          HOST_WIDE_INT_PRINT_DEC" queries\n",
+          alias_stats.call_may_clobber_ref_p_no_alias,
+          alias_stats.call_may_clobber_ref_p_no_alias
+          + alias_stats.call_may_clobber_ref_p_may_alias);
+}
+
+
+/* Return true, if dereferencing PTR may alias with a global variable.  */
 
-static void
-setup_pointers_and_addressables (struct alias_info *ai)
+bool
+ptr_deref_may_alias_global_p (tree ptr)
 {
-  size_t num_addressable_vars, num_pointers;
-  referenced_var_iterator rvi;
-  tree var;
-  VEC (tree, heap) *varvec = NULL;
-  safe_referenced_var_iterator srvi;
-
-  /* Size up the arrays ADDRESSABLE_VARS and POINTERS.  */
-  num_addressable_vars = num_pointers = 0;
-  
-  FOR_EACH_REFERENCED_VAR (var, rvi)
-    {
-      if (may_be_aliased (var))
-       num_addressable_vars++;
-
-      if (POINTER_TYPE_P (TREE_TYPE (var)))
-       {
-         /* Since we don't keep track of volatile variables, assume that
-            these pointers are used in indirect store operations.  */
-         if (TREE_THIS_VOLATILE (var))
-           pointer_set_insert (ai->dereferenced_ptrs, var);
-
-         num_pointers++;
-       }
-    }
-
-  /* Create ADDRESSABLE_VARS and POINTERS.  Note that these arrays are
-     always going to be slightly bigger than we actually need them
-     because some TREE_ADDRESSABLE variables will be marked
-     non-addressable below and only pointers with unique symbol tags are
-     going to be added to POINTERS.  */
-  ai->addressable_vars = XCNEWVEC (struct alias_map_d *, num_addressable_vars);
-  ai->pointers = XCNEWVEC (struct alias_map_d *, num_pointers);
-  ai->num_addressable_vars = 0;
-  ai->num_pointers = 0;
-
-  FOR_EACH_REFERENCED_VAR_SAFE (var, varvec, srvi)
-    {
-      /* Name memory tags already have flow-sensitive aliasing
-        information, so they need not be processed by
-        compute_flow_insensitive_aliasing.  Similarly, symbol memory
-        tags are already accounted for when we process their
-        associated pointer. 
-      
-         Structure fields, on the other hand, have to have some of this
-         information processed for them, but it's pointless to mark them
-         non-addressable (since they are fake variables anyway).  */
-      if (MTAG_P (var))
-       continue;
-
-      /* Remove the ADDRESSABLE flag from every addressable variable whose
-         address is not needed anymore.  This is caused by the propagation
-         of ADDR_EXPR constants into INDIRECT_REF expressions and the
-         removal of dead pointer assignments done by the early scalar
-         cleanup passes.  */
-      if (TREE_ADDRESSABLE (var))
-       {
-         if (!bitmap_bit_p (gimple_addressable_vars (cfun), DECL_UID (var))
-             && TREE_CODE (var) != RESULT_DECL
-             && !is_global_var (var))
-           {
-             bool okay_to_mark = true;
-
-             /* Since VAR is now a regular GIMPLE register, we will need
-                to rename VAR into SSA afterwards.  */
-             mark_sym_for_renaming (var);
-
-             /* The address of VAR is not needed, remove the
-                addressable bit, so that it can be optimized as a
-                regular variable.  */
-             if (okay_to_mark)
-               {
-                 /* The memory partition holding VAR will no longer
-                    contain VAR, and statements referencing it will need
-                    to be updated.  */
-                 if (memory_partition (var))
-                   mark_sym_for_renaming (memory_partition (var));
-
-                 mark_non_addressable (var);
-               }
-           }
-       }
-
-      /* Global variables and addressable locals may be aliased.  Create an
-         entry in ADDRESSABLE_VARS for VAR.  */
-      if (may_be_aliased (var))
-       {
-         create_alias_map_for (var, ai);
-         mark_sym_for_renaming (var);
-       }
-
-      /* Add pointer variables that have been dereferenced to the POINTERS
-         array and create a symbol memory tag for them.  */
-      if (POINTER_TYPE_P (TREE_TYPE (var)))
-       {
-         if (pointer_set_contains (ai->dereferenced_ptrs, var))
-           {
-             tree tag, old_tag;
-             var_ann_t t_ann;
-
-             /* If pointer VAR still doesn't have a memory tag
-                associated with it, create it now or re-use an
-                existing one.  */
-             tag = get_smt_for (var, ai);
-             t_ann = var_ann (tag);
-
-             /* The symbol tag will need to be renamed into SSA
-                afterwards. Note that we cannot do this inside
-                get_smt_for because aliasing may run multiple times
-                and we only create symbol tags the first time.  */
-             mark_sym_for_renaming (tag);
-
-             /* Similarly, if pointer VAR used to have another type
-                tag, we will need to process it in the renamer to
-                remove the stale virtual operands.  */
-             old_tag = symbol_mem_tag (var);
-             if (old_tag)
-               mark_sym_for_renaming (old_tag);
-
-             /* Associate the tag with pointer VAR.  */
-             set_symbol_mem_tag (var, tag);
-           }
-         else
-           {
-             /* The pointer has not been dereferenced.  If it had a
-                symbol memory tag, remove it and mark the old tag for
-                renaming to remove it out of the IL.  */
-             tree tag = symbol_mem_tag (var);
-             if (tag)
-               {
-                 mark_sym_for_renaming (tag);
-                 set_symbol_mem_tag (var, NULL_TREE);
-               }
-           }
-       }
-    }
+  struct ptr_info_def *pi;
 
-  VEC_free (tree, heap, varvec);
-}
+  /* If we end up with a pointer constant here that may point
+     to global memory.  */
+  if (TREE_CODE (ptr) != SSA_NAME)
+    return true;
 
+  pi = SSA_NAME_PTR_INFO (ptr);
 
-/* Determine whether to use .GLOBAL_VAR to model call clobbering
-   semantics.  If the function makes no references to global
-   variables and contains at least one call to a non-pure function,
-   then we need to mark the side-effects of the call using .GLOBAL_VAR
-   to represent all possible global memory referenced by the callee.  */
+  /* If we do not have points-to information for this variable,
+     we have to punt.  */
+  if (!pi)
+    return true;
 
-static void
-maybe_create_global_var (void)
-{
-  /* No need to create it, if we have one already.  */
-  if (gimple_global_var (cfun) == NULL_TREE)
-    {
-      struct mem_ref_stats_d *stats = gimple_mem_ref_stats (cfun);
-
-      /* Create .GLOBAL_VAR if there are no call-clobbered
-        variables and the program contains a mixture of pure/const
-        and regular function calls.  This is to avoid the problem
-        described in PR 20115:
-
-             int X;
-             int func_pure (void) { return X; }
-             int func_non_pure (int a) { X += a; }
-             int foo ()
-             {
-               int a = func_pure ();
-               func_non_pure (a);
-               a = func_pure ();
-               return a;
-             }
-
-        Since foo() has no call-clobbered variables, there is
-        no relationship between the calls to func_pure and
-        func_non_pure.  Since func_pure has no side-effects, value
-        numbering optimizations elide the second call to func_pure.
-        So, if we have some pure/const and some regular calls in the
-        program we create .GLOBAL_VAR to avoid missing these
-        relations.  */
-      if (bitmap_empty_p (gimple_call_clobbered_vars (cfun))
-         && stats->num_call_sites > 0
-         && stats->num_pure_const_call_sites > 0
-         && stats->num_call_sites > stats->num_pure_const_call_sites)
-       create_global_var ();
-    }
+  return pt_solution_includes_global (&pi->pt);
 }
 
+/* Return true if dereferencing PTR may alias DECL.  */
 
-/* Return TRUE if pointer PTR may point to variable VAR.
-   
-   MEM_ALIAS_SET is the alias set for the memory location pointed-to by PTR
-       This is needed because when checking for type conflicts we are
-       interested in the alias set of the memory location pointed-to by
-       PTR.  The alias set of PTR itself is irrelevant.
-   
-   VAR_ALIAS_SET is the alias set for VAR.  */
-
-bool
-may_alias_p (tree ptr, alias_set_type mem_alias_set,
-            tree var, alias_set_type var_alias_set,
-            bool alias_set_only)
+static bool
+ptr_deref_may_alias_decl_p (tree ptr, tree decl)
 {
-  tree mem;
-
-  alias_stats.alias_queries++;
-  alias_stats.simple_queries++;
-
-  /* By convention, a variable cannot alias itself.  */
-  mem = symbol_mem_tag (ptr);
-  if (mem == var)
-    {
-      alias_stats.alias_noalias++;
-      alias_stats.simple_resolved++;
-      return false;
-    }
-
-  /* If -fargument-noalias-global is > 2, pointer arguments may
-     not point to anything else.  */
-  if (flag_argument_noalias > 2 && TREE_CODE (ptr) == PARM_DECL)
-    {
-      alias_stats.alias_noalias++;
-      alias_stats.simple_resolved++;
-      return false;
-    }
-
-  /* If -fargument-noalias-global is > 1, pointer arguments may
-     not point to global variables.  */
-  if (flag_argument_noalias > 1 && is_global_var (var)
-      && TREE_CODE (ptr) == PARM_DECL)
-    {
-      alias_stats.alias_noalias++;
-      alias_stats.simple_resolved++;
-      return false;
-    }
-
-  /* If the pointed to memory has alias set zero, or the pointer
-     is ref-all, or the pointer decl is marked that no TBAA is to
-     be applied, the MEM can alias VAR.  */
-  if (mem_alias_set == 0
-      || DECL_POINTER_ALIAS_SET (ptr) == 0
-      || TYPE_REF_CAN_ALIAS_ALL (TREE_TYPE (ptr))
-      || DECL_NO_TBAA_P (ptr))
-    {
-      alias_stats.alias_mayalias++;
-      alias_stats.simple_resolved++;
-      return true;
-    }
-
-  gcc_assert (TREE_CODE (mem) == SYMBOL_MEMORY_TAG);
-
-  alias_stats.tbaa_queries++;
-
-  /* If the alias sets don't conflict then MEM cannot alias VAR.  */
-  if (mem_alias_set != var_alias_set
-      && !alias_set_subset_of (mem_alias_set, var_alias_set))
-    {
-      alias_stats.alias_noalias++;
-      alias_stats.tbaa_resolved++;
-      return false;
-    }
-
-  /* If VAR is a record or union type, PTR cannot point into VAR
-     unless there is some explicit address operation in the
-     program that can reference a field of the type pointed-to by
-     PTR.  This also assumes that the types of both VAR and PTR
-     are contained within the compilation unit, and that there is
-     no fancy addressing arithmetic associated with any of the
-     types involved.  */
-  if (mem_alias_set != 0 && var_alias_set != 0)
-    {
-      tree ptr_type = TREE_TYPE (ptr);
-      tree var_type = TREE_TYPE (var);
-      
-      /* The star count is -1 if the type at the end of the
-        pointer_to chain is not a record or union type. */ 
-      if (!alias_set_only && 
-         0 /* FIXME tuples ipa_type_escape_star_count_of_interesting_type (var_type) >= 0*/)
-       {
-         int ptr_star_count = 0;
-
-         /* ipa_type_escape_star_count_of_interesting_type is a
-            little too restrictive for the pointer type, need to
-            allow pointers to primitive types as long as those
-            types cannot be pointers to everything.  */
-         while (POINTER_TYPE_P (ptr_type))
-           {
-             /* Strip the *s off.  */ 
-             ptr_type = TREE_TYPE (ptr_type);
-             ptr_star_count++;
-           }
-         
-         /* There does not appear to be a better test to see if
-            the pointer type was one of the pointer to everything
-            types.  */
-         if (ptr_star_count > 0)
-           {
-             alias_stats.structnoaddress_queries++;
-             if (ipa_type_escape_field_does_not_clobber_p (var_type, 
-                                                           TREE_TYPE (ptr)))
-               {
-                 alias_stats.structnoaddress_resolved++;
-                 alias_stats.alias_noalias++;
-                 return false;
-               }
-           }
-         else if (ptr_star_count == 0)
-           {
-             /* If PTR_TYPE was not really a pointer to type, it cannot 
-                alias.  */ 
-             alias_stats.structnoaddress_queries++;
-             alias_stats.structnoaddress_resolved++;
-             alias_stats.alias_noalias++;
-             return false;
-           }
-       }
-    }
+  struct ptr_info_def *pi;
 
-  alias_stats.alias_mayalias++;
-  return true;
-}
+  /* ???  During SCCVN/PRE we can end up with *&x during valueizing
+     operands.  Likewise we can end up with dereferencing constant
+     pointers.  Just bail out in these cases for now.  */
+  if (TREE_CODE (ptr) == ADDR_EXPR
+      || TREE_CODE (ptr) == INTEGER_CST)
+    return true;
 
-/* Return true, if PTR may point to a global variable.  */
+  gcc_assert (TREE_CODE (ptr) == SSA_NAME
+             && (TREE_CODE (decl) == VAR_DECL
+                 || TREE_CODE (decl) == PARM_DECL
+                 || TREE_CODE (decl) == RESULT_DECL));
 
-bool
-may_point_to_global_var (tree ptr)
-{
-  struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
+  /* Non-aliased variables can not be pointed to.  */
+  if (!may_be_aliased (decl))
+    return false;
 
-  /* If we do not have points-to information for this variable,
-     we have to punt.  */
-  if (!pi
-      || !pi->name_mem_tag)
+  /* If we do not have useful points-to information for this pointer
+     we cannot disambiguate anything else.  */
+  pi = SSA_NAME_PTR_INFO (ptr);
+  if (!pi)
     return true;
 
-  /* The name memory tag is marked as global variable if the points-to
-     set contains a global variable.  */
-  return is_global_var (pi->name_mem_tag);
+  return pt_solution_includes (&pi->pt, decl);
 }
 
-/* Add ALIAS to the set of variables that may alias VAR.  */
+/* Return true if dereferenced PTR1 and PTR2 may alias.  */
 
-static void
-add_may_alias (tree var, tree alias)
+static bool
+ptr_derefs_may_alias_p (tree ptr1, tree ptr2)
 {
-  /* Don't allow self-referential aliases.  */
-  gcc_assert (var != alias);
-
-  /* ALIAS must be addressable if it's being added to an alias set.  */
-#if 1
-  TREE_ADDRESSABLE (alias) = 1;
-#else
-  gcc_assert (may_be_aliased (alias));
-#endif
-
-  /* VAR must be a symbol or a name tag.  */
-  gcc_assert (TREE_CODE (var) == SYMBOL_MEMORY_TAG
-              || TREE_CODE (var) == NAME_MEMORY_TAG);
-
-  if (MTAG_ALIASES (var) == NULL)
-    MTAG_ALIASES (var) = BITMAP_ALLOC (&alias_bitmap_obstack);
-  
-  bitmap_set_bit (MTAG_ALIASES (var), DECL_UID (alias));
-}
+  struct ptr_info_def *pi1, *pi2;
 
+  /* ???  During SCCVN/PRE we can end up with *&x during valueizing
+     operands.  Likewise we can end up with dereferencing constant
+     pointers.  Just bail out in these cases for now.  */
+  if (TREE_CODE (ptr1) == ADDR_EXPR
+      || TREE_CODE (ptr1) == INTEGER_CST
+      || TREE_CODE (ptr2) == ADDR_EXPR
+      || TREE_CODE (ptr2) == INTEGER_CST)
+    return true;
 
-/* Mark pointer PTR as pointing to an arbitrary memory location.  */
+  gcc_assert (TREE_CODE (ptr1) == SSA_NAME
+             && TREE_CODE (ptr2) == SSA_NAME);
 
-static void
-set_pt_anything (tree ptr)
-{
-  struct ptr_info_def *pi = get_ptr_info (ptr);
+  /* We may end up with two empty points-to solutions for two same pointers.
+     In this case we still want to say both pointers alias, so shortcut
+     that here.  */
+  if (ptr1 == ptr2)
+    return true;
 
-  pi->pt_anything = 1;
-  /* Anything includes global memory.  */
-  pi->pt_global_mem = 1;
-  pi->pt_vars = NULL;
+  /* If we do not have useful points-to information for either pointer
+     we cannot disambiguate anything else.  */
+  pi1 = SSA_NAME_PTR_INFO (ptr1);
+  pi2 = SSA_NAME_PTR_INFO (ptr2);
+  if (!pi1 || !pi2)
+    return true;
 
-  /* The pointer used to have a name tag, but we now found it pointing
-     to an arbitrary location.  The name tag needs to be renamed and
-     disassociated from PTR.  */
-  if (pi->name_mem_tag)
-    {
-      mark_sym_for_renaming (pi->name_mem_tag);
-      pi->name_mem_tag = NULL_TREE;
-    }
+  return pt_solutions_intersect (&pi1->pt, &pi2->pt);
 }
 
-
 /* Return true if STMT is an "escape" site from the current function.  Escape
    sites those statements which might expose the address of a variable
    outside the current function.  STMT is an escape site iff:
@@ -3158,250 +262,45 @@ is_escape_site (gimple stmt)
       if (lhs == NULL_TREE)
        return ESCAPE_UNKNOWN;
 
-      if (gimple_assign_cast_p (stmt))
-       {
-         tree from = TREE_TYPE (gimple_assign_rhs1 (stmt));
-         tree to = TREE_TYPE (lhs);
-
-         /* If the RHS is a conversion between a pointer and an integer, the
-            pointer escapes since we can't track the integer.  */
-         if (POINTER_TYPE_P (from) && !POINTER_TYPE_P (to))
-           return ESCAPE_BAD_CAST;
-       }
-
-      /* If the LHS is an SSA name, it can't possibly represent a non-local
-        memory store.  */
-      if (TREE_CODE (lhs) == SSA_NAME)
-       return NO_ESCAPE;
-
-      /* If the LHS is a non-global decl, it isn't a non-local memory store.
-        If the LHS escapes, the RHS escape is dealt with in the PTA solver.  */
-      if (DECL_P (lhs)
-         && !is_global_var (lhs))
-       return NO_ESCAPE;
-
-      /* FIXME: LHS is not an SSA_NAME.  Even if it's an assignment to a
-        local variables we cannot be sure if it will escape, because we
-        don't have information about objects not in SSA form.  Need to
-        implement something along the lines of
-
-        J.-D. Choi, M. Gupta, M. J. Serrano, V. C. Sreedhar, and S. P.
-        Midkiff, ``Escape analysis for java,'' in Proceedings of the
-        Conference on Object-Oriented Programming Systems, Languages, and
-        Applications (OOPSLA), pp. 1-19, 1999.  */
-      return ESCAPE_STORED_IN_GLOBAL;
-    }
-  else if (gimple_code (stmt) == GIMPLE_RETURN)
-    return ESCAPE_TO_RETURN;
-
-  return NO_ESCAPE;
-}
-
-/* Create a new memory tag of type TYPE.
-   Does NOT push it into the current binding.  */
-
-tree
-create_tag_raw (enum tree_code code, tree type, const char *prefix)
-{
-  tree tmp_var;
-
-  tmp_var = build_decl (code, create_tmp_var_name (prefix), type);
-
-  /* Memory tags are always writable and non-static.  */
-  TREE_READONLY (tmp_var) = 0;
-  TREE_STATIC (tmp_var) = 0;
-
-  /* It doesn't start out global.  */
-  MTAG_GLOBAL (tmp_var) = 0;
-  TREE_USED (tmp_var) = 1;
-
-  return tmp_var;
-}
-
-/* Create a new memory tag of type TYPE.  If IS_TYPE_TAG is true, the tag
-   is considered to represent all the pointers whose pointed-to types are
-   in the same alias set class.  Otherwise, the tag represents a single
-   SSA_NAME pointer variable.  */
-
-static tree
-create_memory_tag (tree type, bool is_type_tag)
-{
-  tree tag = create_tag_raw (is_type_tag ? SYMBOL_MEMORY_TAG : NAME_MEMORY_TAG,
-                            type, (is_type_tag) ? "SMT" : "NMT");
-
-  /* By default, memory tags are local variables.  Alias analysis will
-     determine whether they should be considered globals.  */
-  DECL_CONTEXT (tag) = current_function_decl;
-
-  /* Memory tags are by definition addressable.  */
-  TREE_ADDRESSABLE (tag) = 1;
-
-  set_symbol_mem_tag (tag, NULL_TREE);
-
-  /* Add the tag to the symbol table.  */
-  add_referenced_var (tag);
-
-  return tag;
-}
-
-
-/* Create a name memory tag to represent a specific SSA_NAME pointer P_i.
-   This is used if P_i has been found to point to a specific set of
-   variables or to a non-aliased memory location like the address returned
-   by malloc functions.  */
-
-static tree
-get_nmt_for (tree ptr)
-{
-  struct ptr_info_def *pi = get_ptr_info (ptr);
-  tree tag = pi->name_mem_tag;
-
-  if (tag == NULL_TREE)
-    tag = create_memory_tag (TREE_TYPE (TREE_TYPE (ptr)), false);
-  return tag;
-}
-
-
-/* Return the symbol memory tag associated to pointer PTR.  A memory
-   tag is an artificial variable that represents the memory location
-   pointed-to by PTR.  It is used to model the effects of pointer
-   de-references on addressable variables.
-   
-   AI points to the data gathered during alias analysis.  This
-   function populates the array AI->POINTERS.  */
-
-static tree
-get_smt_for (tree ptr, struct alias_info *ai)
-{
-  size_t i;
-  tree tag;
-  tree tag_type = TREE_TYPE (TREE_TYPE (ptr));
-  alias_set_type tag_set;
-
-  /* Get the alias set to be used for the pointed-to memory.  If that
-     differs from what we would get from looking at the type adjust
-     the tag_type to void to make sure we get a proper alias set from
-     just looking at the SMT we create.  */
-  tag_set = get_alias_set (tag_type);
-  if (TYPE_REF_CAN_ALIAS_ALL (TREE_TYPE (ptr))
-      /* This is overly conservative but we do not want to assign
-         restrict alias sets here (which if they are not assigned
-         are -2 but still "known").  */
-      || DECL_POINTER_ALIAS_SET_KNOWN_P (ptr))
-    {
-      tag_set = 0;
-      tag_type = void_type_node;
-    }
-
-  /* To avoid creating unnecessary memory tags, only create one memory tag
-     per alias set class.  Note that it may be tempting to group
-     memory tags based on conflicting alias sets instead of
-     equivalence.  That would be wrong because alias sets are not
-     necessarily transitive (as demonstrated by the libstdc++ test
-     23_containers/vector/cons/4.cc).  Given three alias sets A, B, C
-     such that conflicts (A, B) == true and conflicts (A, C) == true,
-     it does not necessarily follow that conflicts (B, C) == true.  */
-  for (i = 0, tag = NULL_TREE; i < ai->num_pointers; i++)
-    {
-      struct alias_map_d *curr = ai->pointers[i];
-      tree curr_tag = symbol_mem_tag (curr->var);
-      if (tag_set == curr->set)
-       {
-         tag = curr_tag;
-         break;
-       }
-    }
-
-  /* If VAR cannot alias with any of the existing memory tags, create a new
-     tag for PTR and add it to the POINTERS array.  */
-  if (tag == NULL_TREE)
-    {
-      struct alias_map_d *alias_map;
-
-      /* If PTR did not have a symbol tag already, create a new SMT.*
-        artificial variable representing the memory location
-        pointed-to by PTR.  */
-      tag = symbol_mem_tag (ptr);
-      if (tag == NULL_TREE
-         || tag_set != get_alias_set (tag))
-       tag = create_memory_tag (tag_type, true);
-
-      /* Add PTR to the POINTERS array.  Note that we are not interested in
-        PTR's alias set.  Instead, we cache the alias set for the memory that
-        PTR points to.  */
-      alias_map = XCNEW (struct alias_map_d);
-      alias_map->var = ptr;
-      alias_map->set = tag_set;
-      ai->pointers[ai->num_pointers++] = alias_map;
-    }
-
-  /* If the pointed-to type is volatile, so is the tag.  */
-  TREE_THIS_VOLATILE (tag) |= TREE_THIS_VOLATILE (tag_type);
-
-  /* Make sure that the symbol tag has the same alias set as the
-     pointed-to type or at least accesses through the pointer will
-     alias that set.  The latter can happen after the vectorizer
-     created pointers of vector type.  */
-  gcc_assert (tag_set == get_alias_set (tag)
-             || alias_set_subset_of (tag_set, get_alias_set (tag)));
-
-  return tag;
-}
+      if (gimple_assign_cast_p (stmt))
+       {
+         tree from = TREE_TYPE (gimple_assign_rhs1 (stmt));
+         tree to = TREE_TYPE (lhs);
 
+         /* If the RHS is a conversion between a pointer and an integer, the
+            pointer escapes since we can't track the integer.  */
+         if (POINTER_TYPE_P (from) && !POINTER_TYPE_P (to))
+           return ESCAPE_BAD_CAST;
+       }
 
-/* Create GLOBAL_VAR, an artificial global variable to act as a
-   representative of all the variables that may be clobbered by function
-   calls.  */
+      /* If the LHS is an SSA name, it can't possibly represent a non-local
+        memory store.  */
+      if (TREE_CODE (lhs) == SSA_NAME)
+       return NO_ESCAPE;
 
-static void
-create_global_var (void)
-{
-  tree global_var = build_decl (VAR_DECL, get_identifier (".GLOBAL_VAR"),
-                                void_type_node);
-  DECL_ARTIFICIAL (global_var) = 1;
-  TREE_READONLY (global_var) = 0;
-  DECL_EXTERNAL (global_var) = 1;
-  TREE_STATIC (global_var) = 1;
-  TREE_USED (global_var) = 1;
-  DECL_CONTEXT (global_var) = NULL_TREE;
-  TREE_THIS_VOLATILE (global_var) = 0;
-  TREE_ADDRESSABLE (global_var) = 0;
-
-  create_var_ann (global_var);
-  mark_call_clobbered (global_var, ESCAPE_UNKNOWN);
-  add_referenced_var (global_var);
-  mark_sym_for_renaming (global_var);
-  cfun->gimple_df->global_var = global_var;
-}
+      /* If the LHS is a non-global decl, it isn't a non-local memory store.
+        If the LHS escapes, the RHS escape is dealt with in the PTA solver.  */
+      if (DECL_P (lhs)
+         && !is_global_var (lhs))
+       return NO_ESCAPE;
 
+      /* FIXME: LHS is not an SSA_NAME.  Even if it's an assignment to a
+        local variables we cannot be sure if it will escape, because we
+        don't have information about objects not in SSA form.  Need to
+        implement something along the lines of
 
-/* Dump alias statistics on FILE.  */
+        J.-D. Choi, M. Gupta, M. J. Serrano, V. C. Sreedhar, and S. P.
+        Midkiff, ``Escape analysis for java,'' in Proceedings of the
+        Conference on Object-Oriented Programming Systems, Languages, and
+        Applications (OOPSLA), pp. 1-19, 1999.  */
+      return ESCAPE_STORED_IN_GLOBAL;
+    }
+  else if (gimple_code (stmt) == GIMPLE_RETURN)
+    return ESCAPE_TO_RETURN;
 
-static void 
-dump_alias_stats (FILE *file)
-{
-  const char *funcname
-    = lang_hooks.decl_printable_name (current_function_decl, 2);
-  fprintf (file, "\nAlias statistics for %s\n\n", funcname);
-  fprintf (file, "Total alias queries:\t%u\n", alias_stats.alias_queries);
-  fprintf (file, "Total alias mayalias results:\t%u\n", 
-          alias_stats.alias_mayalias);
-  fprintf (file, "Total alias noalias results:\t%u\n",
-          alias_stats.alias_noalias);
-  fprintf (file, "Total simple queries:\t%u\n",
-          alias_stats.simple_queries);
-  fprintf (file, "Total simple resolved:\t%u\n",
-          alias_stats.simple_resolved);
-  fprintf (file, "Total TBAA queries:\t%u\n",
-          alias_stats.tbaa_queries);
-  fprintf (file, "Total TBAA resolved:\t%u\n",
-          alias_stats.tbaa_resolved);
-  fprintf (file, "Total non-addressable structure type queries:\t%u\n",
-          alias_stats.structnoaddress_queries);
-  fprintf (file, "Total non-addressable structure type resolved:\t%u\n",
-          alias_stats.structnoaddress_resolved);
+  return NO_ESCAPE;
 }
-  
+
 
 /* Dump alias information on FILE.  */
 
@@ -3414,11 +313,7 @@ dump_alias_info (FILE *file)
   referenced_var_iterator rvi;
   tree var;
 
-  fprintf (file, "\nAlias information for %s\n\n", funcname);
-
-  dump_memory_partitions (file);
-
-  fprintf (file, "\nFlow-insensitive alias information for %s\n\n", funcname);
+  fprintf (file, "\n\nAlias information for %s\n\n", funcname);
 
   fprintf (file, "Aliased symbols\n\n");
   
@@ -3428,46 +323,22 @@ dump_alias_info (FILE *file)
        dump_variable (file, var);
     }
 
-  fprintf (file, "\nDereferenced pointers\n\n");
-
-  FOR_EACH_REFERENCED_VAR (var, rvi)
-    if (symbol_mem_tag (var))
-      dump_variable (file, var);
-
-  fprintf (file, "\nSymbol memory tags\n\n");
-  
-  FOR_EACH_REFERENCED_VAR (var, rvi)
-    {
-      if (TREE_CODE (var) == SYMBOL_MEMORY_TAG)
-       dump_variable (file, var);
-    }
-
-  fprintf (file, "\n\nFlow-sensitive alias information for %s\n\n", funcname);
+  fprintf (file, "\n\nFlow-insensitive points-to information for %s\n\n", funcname);
 
-  fprintf (file, "SSA_NAME pointers\n\n");
   for (i = 1; i < num_ssa_names; i++)
     {
       tree ptr = ssa_name (i);
       struct ptr_info_def *pi;
       
-      if (ptr == NULL_TREE)
+      if (ptr == NULL_TREE
+         || SSA_NAME_IN_FREE_LIST (ptr))
        continue;
 
       pi = SSA_NAME_PTR_INFO (ptr);
-      if (!SSA_NAME_IN_FREE_LIST (ptr)
-         && pi
-         && pi->name_mem_tag)
+      if (pi)
        dump_points_to_info_for (file, ptr);
     }
 
-  fprintf (file, "\nName memory tags\n\n");
-  
-  FOR_EACH_REFERENCED_VAR (var, rvi)
-    {
-      if (TREE_CODE (var) == NAME_MEMORY_TAG)
-       dump_variable (file, var);
-    }
-
   fprintf (file, "\n");
 }
 
@@ -3495,6 +366,7 @@ get_ptr_info (tree t)
   if (pi == NULL)
     {
       pi = GGC_CNEW (struct ptr_info_def);
+      pt_solution_reset (&pi->pt);
       SSA_NAME_PTR_INFO (t) = pi;
     }
 
@@ -3512,30 +384,24 @@ dump_points_to_info_for (FILE *file, tree ptr)
 
   if (pi)
     {
-      if (pi->name_mem_tag)
-       {
-         fprintf (file, ", name memory tag: ");
-         print_generic_expr (file, pi->name_mem_tag, dump_flags);
-       }
-
-      if (pi->is_dereferenced)
-       fprintf (file, ", is dereferenced");
-      else if (pi->memory_tag_needed)
-       fprintf (file, ", is dereferenced in call");
+      if (pi->pt.anything)
+       fprintf (file, ", points-to anything");
 
-      if (pi->value_escapes_p)
-       fprintf (file, ", its value escapes");
+      if (pi->pt.nonlocal)
+       fprintf (file, ", points-to non-local");
 
-      if (pi->pt_anything)
-       fprintf (file, ", points-to anything");
+      if (pi->pt.escaped)
+       fprintf (file, ", points-to escaped");
 
-      if (pi->pt_null)
+      if (pi->pt.null)
        fprintf (file, ", points-to NULL");
 
-      if (pi->pt_vars)
+      if (pi->pt.vars)
        {
          fprintf (file, ", points-to vars: ");
-         dump_decl_set (file, pi->pt_vars);
+         dump_decl_set (file, pi->pt.vars);
+         if (pi->pt.vars_contains_global)
+           fprintf (file, " (includes global vars)");
        }
     }
 
@@ -3551,249 +417,717 @@ debug_points_to_info_for (tree var)
   dump_points_to_info_for (stderr, var);
 }
 
+/* Return 1 if TYPE1 and TYPE2 are to be considered equivalent for the
+   purpose of TBAA.  Return 0 if they are distinct and -1 if we cannot
+   decide.  */
 
-/* Dump points-to information into FILE.  NOTE: This function is slow, as
-   it needs to traverse the whole CFG looking for pointer SSA_NAMEs.  */
+static inline int
+same_type_for_tbaa (tree type1, tree type2)
+{
+  type1 = TYPE_MAIN_VARIANT (type1);
+  type2 = TYPE_MAIN_VARIANT (type2);
 
-void
-dump_points_to_info (FILE *file ATTRIBUTE_UNUSED)
+  /* If we would have to do structural comparison bail out.  */
+  if (TYPE_STRUCTURAL_EQUALITY_P (type1)
+      || TYPE_STRUCTURAL_EQUALITY_P (type2))
+    return -1;
+
+  /* Compare the canonical types.  */
+  if (TYPE_CANONICAL (type1) == TYPE_CANONICAL (type2))
+    return 1;
+
+  /* ???  Array types are not properly unified in all cases as we have
+     spurious changes in the index types for example.  Removing this
+     causes all sorts of problems with the Fortran frontend.  */
+  if (TREE_CODE (type1) == ARRAY_TYPE
+      && TREE_CODE (type2) == ARRAY_TYPE)
+    return -1;
+
+  /* The types are known to be not equal.  */
+  return 0;
+}
+
+/* Determine if the two component references REF1 and REF2 which are
+   based on access types TYPE1 and TYPE2 and of which at least one is based
+   on an indirect reference may alias.  */
+
+static bool
+nonaliasing_component_refs_p (tree ref1, tree type1,
+                             HOST_WIDE_INT offset1, HOST_WIDE_INT max_size1,
+                             tree ref2, tree type2,
+                             HOST_WIDE_INT offset2, HOST_WIDE_INT max_size2)
+{
+  /* If one reference is a component references through pointers try to find a
+     common base and apply offset based disambiguation.  This handles
+     for example
+       struct A { int i; int j; } *q;
+       struct B { struct A a; int k; } *p;
+     disambiguating q->i and p->a.j.  */
+  tree *refp;
+  int same_p;
+
+  /* Now search for the type1 in the access path of ref2.  This
+     would be a common base for doing offset based disambiguation on.  */
+  /* Skip the outermost ref - we would have caught that earlier.  */
+  refp = &TREE_OPERAND (ref2, 0);
+  while (handled_component_p (*refp)
+        && same_type_for_tbaa (TREE_TYPE (*refp), type1) == 0)
+    refp = &TREE_OPERAND (*refp, 0);
+  same_p = same_type_for_tbaa (TREE_TYPE (*refp), type1);
+  /* If we couldn't compare types we have to bail out.  */
+  if (same_p == -1)
+    return true;
+  else if (same_p == 1)
+    {
+      HOST_WIDE_INT offadj, sztmp, msztmp;
+      get_ref_base_and_extent (*refp, &offadj, &sztmp, &msztmp);
+      offset2 -= offadj;
+      return ranges_overlap_p (offset1, max_size1, offset2, max_size2);
+    }
+  /* If we didn't find a common base, try the other way around.  */
+  refp = &TREE_OPERAND (ref1, 0);
+  while (handled_component_p (*refp)
+        && same_type_for_tbaa (TREE_TYPE (*refp), type2) == 0)
+    refp = &TREE_OPERAND (*refp, 0);
+  same_p = same_type_for_tbaa (TREE_TYPE (*refp), type2);
+  /* If we couldn't compare types we have to bail out.  */
+  if (same_p == -1)
+    return true;
+  else if (same_p == 1)
+    {
+      HOST_WIDE_INT offadj, sztmp, msztmp;
+      get_ref_base_and_extent (*refp, &offadj, &sztmp, &msztmp);
+      offset1 -= offadj;
+      return ranges_overlap_p (offset1, max_size1, offset2, max_size2);
+    }
+  /* If we have two type access paths B1.path1 and B2.path2 they may
+     only alias if either B1 is in B2.path2 or B2 is in B1.path1.  */
+  return false;
+}
+
+/* Return true if two memory references based on the variables BASE1
+   and BASE2 constrained to [OFFSET1, OFFSET1 + MAX_SIZE1[ and
+   [OFFSET2, OFFSET2 + MAX_SIZE2[ may alias.  */
+
+static bool
+decl_refs_may_alias_p (tree base1,
+                      HOST_WIDE_INT offset1, HOST_WIDE_INT max_size1,
+                      tree base2,
+                      HOST_WIDE_INT offset2, HOST_WIDE_INT max_size2)
 {
-  basic_block bb;
-  gimple_stmt_iterator si;
-  ssa_op_iter iter;
-  const char *fname =
-    lang_hooks.decl_printable_name (current_function_decl, 2);
-  referenced_var_iterator rvi;
-  tree var;
+  gcc_assert (SSA_VAR_P (base1) && SSA_VAR_P (base2));
 
-  fprintf (file, "\n\nPointed-to sets for pointers in %s\n\n", fname);
+  /* If both references are based on different variables, they cannot alias.  */
+  if (!operand_equal_p (base1, base2, 0))
+    return false;
 
-  /* First dump points-to information for the default definitions of
-     pointer variables.  This is necessary because default definitions are
-     not part of the code.  */
-  FOR_EACH_REFERENCED_VAR (var, rvi)
+  /* If both references are based on the same variable, they cannot alias if
+     the accesses do not overlap.  */
+  return ranges_overlap_p (offset1, max_size1, offset2, max_size2);
+}
+
+/* Return true if an indirect reference based on *PTR1 constrained
+   to [OFFSET1, OFFSET1 + MAX_SIZE1[ may alias a variable based on BASE2
+   constrained to [OFFSET2, OFFSET2 + MAX_SIZE2[.  *PTR1 and BASE2 have
+   the alias sets BASE1_ALIAS_SET and BASE2_ALIAS_SET which can be -1
+   in which case they are computed on-demand.  REF1 and REF2
+   if non-NULL are the complete memory reference trees.  */
+
+static bool
+indirect_ref_may_alias_decl_p (tree ref1, tree ptr1,
+                              HOST_WIDE_INT offset1, HOST_WIDE_INT max_size1,
+                              alias_set_type base1_alias_set,
+                              tree ref2, tree base2,
+                              HOST_WIDE_INT offset2, HOST_WIDE_INT max_size2,
+                              alias_set_type base2_alias_set)
+{
+  /* If only one reference is based on a variable, they cannot alias if
+     the pointer access is beyond the extent of the variable access.
+     (the pointer base cannot validly point to an offset less than zero
+     of the variable).
+     They also cannot alias if the pointer may not point to the decl.  */
+  if (max_size2 != -1
+      && !ranges_overlap_p (offset1, max_size1, 0, offset2 + max_size2))
+    return false;
+  if (!ptr_deref_may_alias_decl_p (ptr1, base2))
+    return false;
+
+  /* Disambiguations that rely on strict aliasing rules follow.  */
+  if (!flag_strict_aliasing)
+    return true;
+
+  /* If the alias set for a pointer access is zero all bets are off.  */
+  if (base1_alias_set == -1)
+    base1_alias_set = get_deref_alias_set (ptr1);
+  if (base1_alias_set == 0)
+    return true;
+  if (base2_alias_set == -1)
+    base2_alias_set = get_alias_set (base2);
+
+  /* If both references are through the same type, they do not alias
+     if the accesses do not overlap.  This does extra disambiguation
+     for mixed/pointer accesses but requires strict aliasing.  */
+  if (same_type_for_tbaa (TREE_TYPE (TREE_TYPE (ptr1)),
+                         TREE_TYPE (base2)) == 1)
+    return ranges_overlap_p (offset1, max_size1, offset2, max_size2);
+
+  /* The only way to access a variable is through a pointer dereference
+     of the same alias set or a subset of it.  */
+  if (base1_alias_set != base2_alias_set
+      && !alias_set_subset_of (base1_alias_set, base2_alias_set))
+    return false;
+
+  /* Do access-path based disambiguation.  */
+  if (ref1 && ref2
+      && handled_component_p (ref1)
+      && handled_component_p (ref2))
+    return nonaliasing_component_refs_p (ref1, TREE_TYPE (TREE_TYPE (ptr1)),
+                                        offset1, max_size1,
+                                        ref2, TREE_TYPE (base2),
+                                        offset2, max_size2);
+
+  return true;
+}
+
+/* Return true if two indirect references based on *PTR1
+   and *PTR2 constrained to [OFFSET1, OFFSET1 + MAX_SIZE1[ and
+   [OFFSET2, OFFSET2 + MAX_SIZE2[ may alias.  *PTR1 and *PTR2 have
+   the alias sets BASE1_ALIAS_SET and BASE2_ALIAS_SET which can be -1
+   in which case they are computed on-demand.  REF1 and REF2
+   if non-NULL are the complete memory reference trees. */
+
+static bool
+indirect_refs_may_alias_p (tree ref1, tree ptr1,
+                          HOST_WIDE_INT offset1, HOST_WIDE_INT max_size1,
+                          alias_set_type base1_alias_set,
+                          tree ref2, tree ptr2,
+                          HOST_WIDE_INT offset2, HOST_WIDE_INT max_size2,
+                          alias_set_type base2_alias_set)
+{
+  /* If both bases are based on pointers they cannot alias if they may not
+     point to the same memory object or if they point to the same object
+     and the accesses do not overlap.  */
+  if (operand_equal_p (ptr1, ptr2, 0))
+    return ranges_overlap_p (offset1, max_size1, offset2, max_size2);
+  if (!ptr_derefs_may_alias_p (ptr1, ptr2))
+    return false;
+
+  /* Disambiguations that rely on strict aliasing rules follow.  */
+  if (!flag_strict_aliasing)
+    return true;
+
+  /* If the alias set for a pointer access is zero all bets are off.  */
+  if (base1_alias_set == -1)
+    base1_alias_set = get_deref_alias_set (ptr1);
+  if (base1_alias_set == 0)
+    return true;
+  if (base2_alias_set == -1)
+    base2_alias_set = get_deref_alias_set (ptr2);
+  if (base2_alias_set == 0)
+    return true;
+
+  /* If both references are through the same type, they do not alias
+     if the accesses do not overlap.  This does extra disambiguation
+     for mixed/pointer accesses but requires strict aliasing.  */
+  if (same_type_for_tbaa (TREE_TYPE (TREE_TYPE (ptr1)),
+                         TREE_TYPE (TREE_TYPE (ptr2))) == 1)
+    return ranges_overlap_p (offset1, max_size1, offset2, max_size2);
+
+  /* Do type-based disambiguation.  */
+  if (base1_alias_set != base2_alias_set
+      && !alias_sets_conflict_p (base1_alias_set, base2_alias_set))
+    return false;
+
+  /* Do access-path based disambiguation.  */
+  if (ref1 && ref2
+      && handled_component_p (ref1)
+      && handled_component_p (ref2))
+    return nonaliasing_component_refs_p (ref1, TREE_TYPE (TREE_TYPE (ptr1)),
+                                        offset1, max_size1,
+                                        ref2, TREE_TYPE (TREE_TYPE (ptr2)),
+                                        offset2, max_size2);
+
+  return true;
+}
+
+/* Return true, if the two memory references REF1 and REF2 may alias.  */
+
+static bool
+refs_may_alias_p_1 (tree ref1, tree ref2)
+{
+  tree base1, base2;
+  HOST_WIDE_INT offset1 = 0, offset2 = 0;
+  HOST_WIDE_INT size1 = -1, size2 = -1;
+  HOST_WIDE_INT max_size1 = -1, max_size2 = -1;
+  bool var1_p, var2_p, ind1_p, ind2_p;
+
+  gcc_assert ((SSA_VAR_P (ref1)
+              || handled_component_p (ref1)
+              || INDIRECT_REF_P (ref1)
+              || TREE_CODE (ref1) == TARGET_MEM_REF)
+             && (SSA_VAR_P (ref2)
+                 || handled_component_p (ref2)
+                 || INDIRECT_REF_P (ref2)
+                 || TREE_CODE (ref2) == TARGET_MEM_REF));
+
+  /* Defer to TBAA if possible.  */
+  if (flag_strict_aliasing
+      && !alias_sets_conflict_p (get_alias_set (ref1), get_alias_set (ref2)))
+    return false;
+
+  /* If one reference is a TARGET_MEM_REF weird things are allowed.  */
+  if (TREE_CODE (ref1) == TARGET_MEM_REF
+      || TREE_CODE (ref2) == TARGET_MEM_REF)
+    return true;
+
+  /* Decompose the references into their base objects and the access.  */
+  base1 = get_ref_base_and_extent (ref1, &offset1, &size1, &max_size1);
+  base2 = get_ref_base_and_extent (ref2, &offset2, &size2, &max_size2);
+
+  /* We can end up with registers or constants as bases for example from
+     *D.1663_44 = VIEW_CONVERT_EXPR<struct DB_LSN>(__tmp$B0F64_59);
+     which is seen as a struct copy.  */
+  if (TREE_CODE (base1) == SSA_NAME
+      || CONSTANT_CLASS_P (base1)
+      || TREE_CODE (base2) == SSA_NAME
+      || CONSTANT_CLASS_P (base2))
+    return false;
+
+  var1_p = SSA_VAR_P (base1);
+  var2_p = SSA_VAR_P (base2);
+  ind1_p = INDIRECT_REF_P (base1);
+  ind2_p = INDIRECT_REF_P (base2);
+  if (var1_p && var2_p)
+    return decl_refs_may_alias_p (base1, offset1, max_size1,
+                                 base2, offset2, max_size2);
+  else if (var1_p && ind2_p)
+    return indirect_ref_may_alias_decl_p (ref2, TREE_OPERAND (base2, 0),
+                                         offset2, max_size2, -1,
+                                         ref1, base1,
+                                         offset1, max_size1, -1);
+  else if (ind1_p && var2_p)
+    return indirect_ref_may_alias_decl_p (ref1, TREE_OPERAND (base1, 0),
+                                         offset1, max_size1, -1,
+                                         ref2, base2,
+                                         offset2, max_size2, -1);
+  else if (ind1_p && ind2_p)
+    return indirect_refs_may_alias_p (ref1, TREE_OPERAND (base1, 0),
+                                     offset1, max_size1, -1,
+                                     ref2, TREE_OPERAND (base2, 0),
+                                     offset2, max_size2, -1);
+
+  gcc_unreachable ();
+}
+
+bool
+refs_may_alias_p (tree ref1, tree ref2)
+{
+  bool res = refs_may_alias_p_1 (ref1, ref2);
+  if (res)
+    ++alias_stats.refs_may_alias_p_may_alias;
+  else
+    ++alias_stats.refs_may_alias_p_no_alias;
+  return res;
+}
+
+
+/* If the call CALL may use the memory reference REF return true,
+   otherwise return false.  */
+
+static bool
+ref_maybe_used_by_call_p_1 (gimple call, tree ref)
+{
+  tree base;
+  unsigned i;
+  int flags = gimple_call_flags (call);
+
+  /* Const functions without a static chain do not implicitly use memory.  */
+  if (!gimple_call_chain (call)
+      && (flags & (ECF_CONST|ECF_NOVOPS)))
+    goto process_args;
+
+  /* If the reference is not based on a decl give up.
+     ???  Handle indirect references by intersecting the call-used
+         solution with that of the pointer.  */
+  base = get_base_address (ref);
+  if (!base
+      || !DECL_P (base))
+    return true;
+
+  /* Check if base is a global static variable that is not read
+     by the function.  */
+  if (TREE_CODE (base) == VAR_DECL
+      && TREE_STATIC (base)
+      && !TREE_PUBLIC (base))
     {
-      if (POINTER_TYPE_P (TREE_TYPE (var)))
-       {
-         tree def = gimple_default_def (cfun, var);
-         if (def)
-           dump_points_to_info_for (file, def);
-       }
+      tree callee = gimple_call_fndecl (call);
+      bitmap not_read;
+
+      if (callee != NULL_TREE
+         && (not_read
+               = ipa_reference_get_not_read_global (cgraph_node (callee)))
+         && bitmap_bit_p (not_read, DECL_UID (base)))
+       goto process_args;
     }
 
-  /* Dump points-to information for every pointer defined in the program.  */
-  FOR_EACH_BB (bb)
+  /* If the base variable is call-used or call-clobbered then
+     it may be used.  */
+  if (flags & (ECF_PURE|ECF_CONST|ECF_LOOPING_CONST_OR_PURE|ECF_NOVOPS))
     {
-      for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
-       {
-         gimple phi = gsi_stmt (si);
-         tree ptr = PHI_RESULT (phi);
-         if (POINTER_TYPE_P (TREE_TYPE (ptr)))
-           dump_points_to_info_for (file, ptr);
-       }
+      if (is_call_used (base))
+       return true;
+    }
+  else
+    {
+      if (is_call_clobbered (base))
+       return true;
+    }
+
+  /* Inspect call arguments for passed-by-value aliases.  */
+process_args:
+  for (i = 0; i < gimple_call_num_args (call); ++i)
+    {
+      tree op = gimple_call_arg (call, i);
+
+      if (TREE_CODE (op) == EXC_PTR_EXPR
+         || TREE_CODE (op) == FILTER_EXPR)
+       continue;
+
+      if (TREE_CODE (op) == WITH_SIZE_EXPR)
+       op = TREE_OPERAND (op, 0);
 
-       for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
-         {
-           gimple stmt = gsi_stmt (si);
-           tree def;
-           FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_DEF)
-             if (TREE_CODE (def) == SSA_NAME
-                 && POINTER_TYPE_P (TREE_TYPE (def)))
-               dump_points_to_info_for (file, def);
-         }
+      if (TREE_CODE (op) != SSA_NAME
+         && !is_gimple_min_invariant (op)
+         && refs_may_alias_p (op, ref))
+       return true;
     }
 
-  fprintf (file, "\n");
+  return false;
+}
+
+static bool
+ref_maybe_used_by_call_p (gimple call, tree ref)
+{
+  bool res = ref_maybe_used_by_call_p_1 (call, ref);
+  if (res)
+    ++alias_stats.ref_maybe_used_by_call_p_may_alias;
+  else
+    ++alias_stats.ref_maybe_used_by_call_p_no_alias;
+  return res;
 }
 
 
-/* Dump points-to info pointed to by PTO into STDERR.  */
+/* If the statement STMT may use the memory reference REF return
+   true, otherwise return false.  */
 
-void
-debug_points_to_info (void)
+bool
+ref_maybe_used_by_stmt_p (gimple stmt, tree ref)
 {
-  dump_points_to_info (stderr);
+  if (is_gimple_assign (stmt))
+    {
+      tree rhs;
+
+      /* All memory assign statements are single.  */
+      if (!gimple_assign_single_p (stmt))
+       return false;
+
+      rhs = gimple_assign_rhs1 (stmt);
+      if (is_gimple_reg (rhs)
+         || is_gimple_min_invariant (rhs)
+         || gimple_assign_rhs_code (stmt) == CONSTRUCTOR)
+       return false;
+
+      return refs_may_alias_p (rhs, ref);
+    }
+  else if (is_gimple_call (stmt))
+    return ref_maybe_used_by_call_p (stmt, ref);
+
+  return true;
 }
 
-/* Dump to FILE the list of variables that may be aliasing VAR.  */
+/* If the call in statement CALL may clobber the memory reference REF
+   return true, otherwise return false.  */
 
-void
-dump_may_aliases_for (FILE *file, tree var)
+static bool
+call_may_clobber_ref_p_1 (gimple call, tree ref)
 {
-  bitmap aliases;
-  
-  aliases = MTAG_ALIASES (var);
-  if (aliases)
+  tree base;
+
+  /* If the call is pure or const it cannot clobber anything.  */
+  if (gimple_call_flags (call)
+      & (ECF_PURE|ECF_CONST|ECF_LOOPING_CONST_OR_PURE|ECF_NOVOPS))
+    return false;
+
+  base = get_base_address (ref);
+  if (!base)
+    return true;
+
+  if (TREE_CODE (base) == SSA_NAME
+      || CONSTANT_CLASS_P (base))
+    return false;
+
+  /* Check if base is a global static variable that is not written
+     by the function.  */
+  if (TREE_CODE (base) == VAR_DECL
+      && TREE_STATIC (base)
+      && !TREE_PUBLIC (base))
     {
-      bitmap_iterator bi;
-      unsigned int i;
-      tree al;
+      tree callee = gimple_call_fndecl (call);
+      bitmap not_written;
 
-      fprintf (file, "{ ");
-      EXECUTE_IF_SET_IN_BITMAP (aliases, 0, i, bi)
-       {
-         al = referenced_var (i);
-         print_generic_expr (file, al, dump_flags);
-         fprintf (file, " ");
-       }
-      fprintf (file, "}");
+      if (callee != NULL_TREE
+         && (not_written
+               = ipa_reference_get_not_written_global (cgraph_node (callee)))
+         && bitmap_bit_p (not_written, DECL_UID (base)))
+       return false;
     }
-}
 
+  if (DECL_P (base))
+    return is_call_clobbered (base);
 
-/* Dump to stderr the list of variables that may be aliasing VAR.  */
+  return true;
+}
 
-void
-debug_may_aliases_for (tree var)
+static bool
+call_may_clobber_ref_p (gimple call, tree ref)
 {
-  dump_may_aliases_for (stderr, var);
+  bool res = call_may_clobber_ref_p_1 (call, ref);
+  if (res)
+    ++alias_stats.call_may_clobber_ref_p_may_alias;
+  else
+    ++alias_stats.call_may_clobber_ref_p_no_alias;
+  return res;
 }
 
-/* Return true if VAR may be aliased.  */
+
+/* If the statement STMT may clobber the memory reference REF return true,
+   otherwise return false.  */
 
 bool
-may_be_aliased (tree var)
+stmt_may_clobber_ref_p (gimple stmt, tree ref)
 {
-  /* Obviously.  */
-  if (TREE_ADDRESSABLE (var))
-    return true;
+  if (is_gimple_call (stmt))
+    {
+      tree lhs = gimple_call_lhs (stmt);
+      if (lhs
+         && !is_gimple_reg (lhs)
+         && refs_may_alias_p (ref, lhs))
+       return true;
 
-  /* Globally visible variables can have their addresses taken by other
-     translation units.  */
-  if (MTAG_P (var)
-      && MTAG_GLOBAL (var))
-    return true;
-  else if (!MTAG_P (var)
-           && (DECL_EXTERNAL (var) || TREE_PUBLIC (var)))
+      return call_may_clobber_ref_p (stmt, ref);
+    }
+  else if (is_gimple_assign (stmt))
+    return refs_may_alias_p (ref, gimple_assign_lhs (stmt));
+  else if (gimple_code (stmt) == GIMPLE_ASM)
     return true;
 
-  /* Automatic variables can't have their addresses escape any other
-     way.  This must be after the check for global variables, as
-     extern declarations do not have TREE_STATIC set.  */
-  if (!TREE_STATIC (var))
-    return false;
-
   return false;
 }
 
-/* The following is based on code in add_stmt_operand to ensure that the
-   same defs/uses/vdefs/vuses will be found after replacing a reference
-   to var (or ARRAY_REF to var) with an INDIRECT_REF to ptr whose value
-   is the address of var.  Return a memtag for the ptr, after adding the 
-   proper may_aliases to it (which are the aliases of var, if it has any,
-   or var itself).  */
+static tree get_continuation_for_phi (gimple, tree, bitmap *);
 
-static tree
-add_may_alias_for_new_tag (tree tag, tree var)
+/* Walk the virtual use-def chain of VUSE until hitting the virtual operand
+   TARGET or a statement clobbering the memory reference REF in which
+   case false is returned.  The walk starts with VUSE, one argument of PHI.  */
+
+static bool
+maybe_skip_until (gimple phi, tree target, tree ref, tree vuse, bitmap *visited)
 {
-  bitmap aliases = NULL;
-  
-  if (MTAG_P (var))
-    aliases = may_aliases (var);
+  if (!*visited)
+    *visited = BITMAP_ALLOC (NULL);
 
-  /* Case 1: |aliases| == 1  */
-  if (aliases
-      && bitmap_single_bit_set_p (aliases))
+  bitmap_set_bit (*visited, SSA_NAME_VERSION (PHI_RESULT (phi)));
+
+  /* Walk until we hit the target.  */
+  while (vuse != target)
     {
-      tree ali = referenced_var (bitmap_first_set_bit (aliases));
-      if (TREE_CODE (ali) == SYMBOL_MEMORY_TAG)
-        return ali;
+      gimple def_stmt = SSA_NAME_DEF_STMT (vuse);
+      /* Recurse for PHI nodes.  */
+      if (gimple_code (def_stmt) == GIMPLE_PHI)
+       {
+         /* An already visited PHI node ends the walk successfully.  */
+         if (bitmap_bit_p (*visited, SSA_NAME_VERSION (PHI_RESULT (def_stmt))))
+           return true;
+         vuse = get_continuation_for_phi (def_stmt, ref, visited);
+         if (!vuse)
+           return false;
+         continue;
+       }
+      /* A clobbering statement or the end of the IL ends it failing.  */
+      else if (gimple_nop_p (def_stmt)
+              || stmt_may_clobber_ref_p (def_stmt, ref))
+       return false;
+      vuse = gimple_vuse (def_stmt);
     }
+  return true;
+}
 
-  /* Case 2: |aliases| == 0  */
-  if (aliases == NULL)
-    add_may_alias (tag, var);
-  else
+/* Starting from a PHI node for the virtual operand of the memory reference
+   REF find a continuation virtual operand that allows to continue walking
+   statements dominating PHI skipping only statements that cannot possibly
+   clobber REF.  Returns NULL_TREE if no suitable virtual operand can
+   be found.  */
+
+static tree
+get_continuation_for_phi (gimple phi, tree ref, bitmap *visited)
+{
+  unsigned nargs = gimple_phi_num_args (phi);
+
+  /* Through a single-argument PHI we can simply look through.  */
+  if (nargs == 1)
+    return PHI_ARG_DEF (phi, 0);
+
+  /* For two arguments try to skip non-aliasing code until we hit
+     the phi argument definition that dominates the other one.  */
+  if (nargs == 2)
     {
-      /* Case 3: |aliases| > 1  */
-      union_alias_set_into (tag, aliases);
+      tree arg0 = PHI_ARG_DEF (phi, 0);
+      tree arg1 = PHI_ARG_DEF (phi, 1);
+      gimple def0 = SSA_NAME_DEF_STMT (arg0);
+      gimple def1 = SSA_NAME_DEF_STMT (arg1);
+
+      if (arg0 == arg1)
+       return arg0;
+      else if (gimple_nop_p (def0)
+              || (!gimple_nop_p (def1)
+                  && dominated_by_p (CDI_DOMINATORS,
+                                     gimple_bb (def1), gimple_bb (def0))))
+       {
+         if (maybe_skip_until (phi, arg0, ref, arg1, visited))
+           return arg0;
+       }
+      else if (gimple_nop_p (def1)
+              || dominated_by_p (CDI_DOMINATORS,
+                                 gimple_bb (def0), gimple_bb (def1)))
+       {
+         if (maybe_skip_until (phi, arg1, ref, arg0, visited))
+           return arg1;
+       }
     }
-  return tag;
+
+  return NULL_TREE;
 }
 
-/* Create a new symbol tag for PTR.  Construct the may-alias list of
-   this type tag so that it has the aliasing of VAR according to the
-   location accessed by EXPR.
+/* Based on the memory reference REF and its virtual use VUSE call
+   WALKER for each virtual use that is equivalent to VUSE, including VUSE
+   itself.  That is, for each virtual use for which its defining statement
+   does not clobber REF.
 
-   Note, the set of aliases represented by the new symbol tag are not
-   marked for renaming.  */
+   WALKER is called with REF, the current virtual use and DATA.  If
+   WALKER returns non-NULL the walk stops and its result is returned.
+   At the end of a non-successful walk NULL is returned.
 
-void
-new_type_alias (tree ptr, tree var, tree expr)
+   TODO: Cache the vector of equivalent vuses per ref, vuse pair.  */
+
+void *
+walk_non_aliased_vuses (tree ref, tree vuse,
+                       void *(*walker)(tree, tree, void *), void *data)
 {
-  tree tag_type = TREE_TYPE (TREE_TYPE (ptr));
-  tree tag;
-  tree ali = NULL_TREE;
-  HOST_WIDE_INT offset, size, maxsize;
-  tree ref;
+  bitmap visited = NULL;
+  void *res;
+
+  timevar_push (TV_ALIAS_STMT_WALK);
+
+  do
+    {
+      gimple def_stmt;
 
-  gcc_assert (symbol_mem_tag (ptr) == NULL_TREE);
-  gcc_assert (!MTAG_P (var));
+      /* ???  Do we want to account this to TV_ALIAS_STMT_WALK?  */
+      res = (*walker) (ref, vuse, data);
+      if (res)
+       break;
 
-  ref = get_ref_base_and_extent (expr, &offset, &size, &maxsize);
-  gcc_assert (ref);
+      def_stmt = SSA_NAME_DEF_STMT (vuse);
+      if (gimple_nop_p (def_stmt))
+       break;
+      else if (gimple_code (def_stmt) == GIMPLE_PHI)
+       vuse = get_continuation_for_phi (def_stmt, ref, &visited);
+      else
+       {
+         if (stmt_may_clobber_ref_p (def_stmt, ref))
+           break;
+         vuse = gimple_vuse (def_stmt);
+       }
+    }
+  while (vuse);
 
-  tag = create_memory_tag (tag_type, true);
-  set_symbol_mem_tag (ptr, tag);
+  if (visited)
+    BITMAP_FREE (visited);
 
-  ali = add_may_alias_for_new_tag (tag, var);
+  timevar_pop (TV_ALIAS_STMT_WALK);
 
-  set_symbol_mem_tag (ptr, ali);
-  MTAG_GLOBAL (tag) = is_global_var (var);
+  return res;
 }
 
 
-/* Reset the call_clobbered flags on our referenced vars.  In
-   theory, this only needs to be done for globals.  */
+/* Based on the memory reference REF call WALKER for each vdef which
+   defining statement may clobber REF, starting with VDEF.  If REF
+   is NULL_TREE, each defining statement is visited.
+
+   WALKER is called with REF, the current vdef and DATA.  If WALKER
+   returns true the walk is stopped, otherwise it continues.
+
+   At PHI nodes walk_aliased_vdefs forks into one walk for reach
+   PHI argument (but only one walk continues on merge points), the
+   return value is true if any of the walks was successful.
+
+   The function returns the number of statements walked.  */
 
 static unsigned int
-reset_cc_flags (void)
+walk_aliased_vdefs_1 (tree ref, tree vdef,
+                     bool (*walker)(tree, tree, void *), void *data,
+                     bitmap *visited, unsigned int cnt)
 {
-  tree var;
-  referenced_var_iterator rvi;
+  do
+    {
+      gimple def_stmt = SSA_NAME_DEF_STMT (vdef);
 
-  FOR_EACH_REFERENCED_VAR (var, rvi)
-    var_ann (var)->call_clobbered = false;
-  return 0;
+      if (*visited
+         && !bitmap_set_bit (*visited, SSA_NAME_VERSION (vdef)))
+       return cnt;
+
+      if (gimple_nop_p (def_stmt))
+       return cnt;
+      else if (gimple_code (def_stmt) == GIMPLE_PHI)
+       {
+         unsigned i;
+         if (!*visited)
+           *visited = BITMAP_ALLOC (NULL);
+         for (i = 0; i < gimple_phi_num_args (def_stmt); ++i)
+           cnt += walk_aliased_vdefs_1 (ref, gimple_phi_arg_def (def_stmt, i),
+                                        walker, data, visited, 0);
+         return cnt;
+       }
+
+      /* ???  Do we want to account this to TV_ALIAS_STMT_WALK?  */
+      cnt++;
+      if ((!ref
+          || stmt_may_clobber_ref_p (def_stmt, ref))
+         && (*walker) (ref, vdef, data))
+       return cnt;
+
+      vdef = gimple_vuse (def_stmt);
+    }
+  while (1);
 }
 
-struct gimple_opt_pass pass_reset_cc_flags =
-{
- {
-  GIMPLE_PASS,
-  NULL,                 /* name */
-  NULL,         /* gate */
-  reset_cc_flags, /* execute */
-  NULL,                         /* sub */
-  NULL,                         /* next */
-  0,                    /* static_pass_number */
-  0,                    /* tv_id */
-  PROP_referenced_vars |PROP_cfg, /* properties_required */
-  0,                    /* properties_provided */
-  0,                    /* properties_destroyed */
-  0,                    /* todo_flags_start */
-  0                     /* todo_flags_finish */
- }
-};
-
-
-/* A dummy pass to cause aliases to be computed via TODO_rebuild_alias.  */
-
-struct gimple_opt_pass pass_build_alias =
+unsigned int
+walk_aliased_vdefs (tree ref, tree vdef,
+                   bool (*walker)(tree, tree, void *), void *data,
+                   bitmap *visited)
 {
- {
-  GIMPLE_PASS,
-  "alias",                 /* name */
-  NULL,                            /* gate */
-  NULL,                     /* execute */
-  NULL,                     /* sub */
-  NULL,                     /* next */
-  0,                        /* static_pass_number */
-  0,                        /* tv_id */
-  PROP_cfg | PROP_ssa,      /* properties_required */
-  PROP_alias,               /* properties_provided */
-  0,                        /* properties_destroyed */
-  0,                        /* todo_flags_start */
-  TODO_rebuild_alias | TODO_dump_func  /* todo_flags_finish */
- }
-};
+  bitmap local_visited = NULL;
+  unsigned int ret;
+
+  timevar_push (TV_ALIAS_STMT_WALK);
+
+  ret = walk_aliased_vdefs_1 (ref, vdef, walker, data,
+                             visited ? visited : &local_visited, 0);
+  if (local_visited)
+    BITMAP_FREE (local_visited);
+
+  timevar_pop (TV_ALIAS_STMT_WALK);
+
+  return ret;
+}
+
diff --git a/gcc/tree-ssa-alias.h b/gcc/tree-ssa-alias.h
new file mode 100644 (file)
index 0000000..dfaa213
--- /dev/null
@@ -0,0 +1,106 @@
+/* Tree based alias analysis and alias oracle.
+   Copyright (C) 2008 Free Software Foundation, Inc.
+   Contributed by Richard Guenther  <rguenther@suse.de>
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, 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 COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef TREE_SSA_ALIAS_H
+#define TREE_SSA_ALIAS_H
+
+#include "coretypes.h"
+
+
+/* The reasons a variable may escape a function.  */
+enum escape_type 
+{
+  NO_ESCAPE = 0,                       /* Doesn't escape.  */
+  ESCAPE_STORED_IN_GLOBAL = 1 << 0,
+  ESCAPE_TO_ASM = 1 << 1,              /* Passed by address to an assembly
+                                          statement.  */
+  ESCAPE_TO_CALL = 1 << 2,             /* Escapes to a function call.  */
+  ESCAPE_BAD_CAST = 1 << 3,            /* Cast from pointer to integer */
+  ESCAPE_TO_RETURN = 1 << 4,           /* Returned from function.  */
+  ESCAPE_TO_PURE_CONST = 1 << 5,       /* Escapes to a pure or constant
+                                          function call.  */
+  ESCAPE_IS_GLOBAL = 1 << 6,           /* Is a global variable.  */
+  ESCAPE_IS_PARM = 1 << 7,             /* Is an incoming function argument.  */
+  ESCAPE_UNKNOWN = 1 << 8              /* We believe it escapes for
+                                          some reason not enumerated
+                                          above.  */
+};
+
+
+/* The points-to solution.
+
+   The points-to solution is a union of pt_vars and the abstract
+   sets specified by the flags.  */
+struct pt_solution GTY(())
+{
+  /* Nonzero if points-to analysis couldn't determine where this pointer
+     is pointing to.  */
+  unsigned int anything : 1;
+
+  /* Nonzero if the points-to set includes any global memory.  Note that
+     even if this is zero pt_vars can still include global variables.  */
+  unsigned int nonlocal : 1;
+
+  /* Nonzero if the points-to set includes any escaped local variable.  */
+  unsigned int escaped : 1;
+
+  /* Nonzero if the points-to set includes 'nothing', the points-to set
+     includes memory at address NULL.  */
+  unsigned int null : 1;
+
+
+  /* Nonzero if the pt_vars bitmap includes a global variable.  */
+  unsigned int vars_contains_global : 1;
+
+  /* Set of variables that this pointer may point to.  */
+  bitmap vars;
+};
+
+
+/* In tree-ssa-alias.c  */
+extern enum escape_type is_escape_site (gimple);
+extern bool ptr_deref_may_alias_global_p (tree);
+extern bool refs_may_alias_p (tree, tree);
+extern bool ref_maybe_used_by_stmt_p (gimple, tree);
+extern bool stmt_may_clobber_ref_p (gimple, tree);
+extern void *walk_non_aliased_vuses (tree, tree,
+                                    void *(*)(tree, tree, void *), void *);
+extern unsigned int walk_aliased_vdefs (tree, tree,
+                                       bool (*)(tree, tree, void *), void *,
+                                       bitmap *);
+extern struct ptr_info_def *get_ptr_info (tree);
+extern void dump_alias_info (FILE *);
+extern void debug_alias_info (void);
+extern void dump_points_to_info_for (FILE *, tree);
+extern void debug_points_to_info_for (tree);
+extern void dump_alias_stats (FILE *);
+
+
+/* In tree-ssa-structalias.c  */
+extern unsigned int compute_may_aliases (void);
+extern void delete_alias_heapvars (void);
+extern bool pt_solution_includes_global (struct pt_solution *);
+extern bool pt_solution_includes (struct pt_solution *, const_tree);
+extern bool pt_solutions_intersect (struct pt_solution *, struct pt_solution *);
+extern void pt_solution_reset (struct pt_solution *);
+extern void dump_pta_stats (FILE *);
+
+
+#endif /* TREE_SSA_ALIAS_H  */
index c7df588..6d8e88e 100644 (file)
@@ -274,8 +274,7 @@ tree
 get_symbol_constant_value (tree sym)
 {
   if (TREE_STATIC (sym)
-      && TREE_READONLY (sym)
-      && !MTAG_P (sym))
+      && TREE_READONLY (sym))
     {
       tree val = DECL_INITIAL (sym);
       if (val)
@@ -528,8 +527,10 @@ likely_value (gimple stmt)
        has_constant_operand = true;
     }
 
-  /* There may be constants in regular rhs operands.  */
-  for (i = is_gimple_call (stmt) + gimple_has_lhs (stmt);
+  /* There may be constants in regular rhs operands.  For calls we
+     have to ignore lhs, fndecl and static chain, otherwise only
+     the lhs.  */
+  for (i = (is_gimple_call (stmt) ? 2 : 0) + gimple_has_lhs (stmt);
        i < gimple_num_ops (stmt); ++i)
     {
       tree op = gimple_op (stmt, i);
@@ -601,7 +602,7 @@ surely_varying_stmt_p (gimple stmt)
     }
 
   /* Any other store operation is not interesting.  */
-  else if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_DEFS))
+  else if (gimple_vdef (stmt))
     return true;
 
   /* Anything other than assignments and conditional jumps are not
@@ -3172,11 +3173,16 @@ gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
   }
 
   if (lhs == NULL_TREE)
-    new_stmt = gimple_build_nop ();
+    {
+      new_stmt = gimple_build_nop ();
+      unlink_stmt_vdef (stmt);
+      release_defs (stmt);
+    }
   else
     {
       new_stmt = gimple_build_assign (lhs, tmp);
-      copy_virtual_operands (new_stmt, stmt);
+      gimple_set_vuse (new_stmt, gimple_vuse (stmt));
+      gimple_set_vdef (new_stmt, gimple_vdef (stmt));
       move_ssa_defining_stmt_for_defs (new_stmt, stmt);
     }
 
@@ -3264,10 +3270,7 @@ execute_fold_all_builtins (void)
          push_stmt_changes (gsi_stmt_ptr (&i));
 
           if (!update_call_from_tree (&i, result))
-            {
-              gimplify_and_update_call_from_tree (&i, result);
-              todoflags |= TODO_rebuild_alias;
-            }
+           gimplify_and_update_call_from_tree (&i, result);
 
          stmt = gsi_stmt (i);
          pop_stmt_changes (gsi_stmt_ptr (&i));
index c82fdaf..97f9f40 100644 (file)
@@ -1114,12 +1114,9 @@ create_outofssa_var_map (coalesce_list_p cl, bitmap used_in_copy)
            bitmap_set_bit (used_in_real_ops, DECL_UID (SSA_NAME_VAR (var)));
 
          /* Validate that virtual ops don't get used in funny ways.  */
-         FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_ALL_VIRTUALS)
-           {
-             bitmap_set_bit (used_in_virtual_ops, 
-                             DECL_UID (SSA_NAME_VAR (var)));
-           }
-
+         if (gimple_vuse (stmt))
+           bitmap_set_bit (used_in_virtual_ops, 
+                           DECL_UID (SSA_NAME_VAR (gimple_vuse (stmt))));
 #endif /* ENABLE_CHECKING */
        }
     }
index 5b36163..a02aee0 100644 (file)
@@ -72,24 +72,6 @@ may_propagate_copy (tree dest, tree orig)
   if (TREE_CODE (dest) == SSA_NAME
       && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (dest))
     return false;
-
-  /* For memory partitions, copies are OK as long as the memory symbol
-     belongs to the partition.  */
-  if (TREE_CODE (dest) == SSA_NAME
-      && TREE_CODE (SSA_NAME_VAR (dest)) == MEMORY_PARTITION_TAG)
-    return (TREE_CODE (orig) == SSA_NAME
-            && !is_gimple_reg (orig)
-           && (SSA_NAME_VAR (dest) == SSA_NAME_VAR (orig)
-               || bitmap_bit_p (MPT_SYMBOLS (SSA_NAME_VAR (dest)),
-                                DECL_UID (SSA_NAME_VAR (orig)))));
-
-  if (TREE_CODE (orig) == SSA_NAME
-      && TREE_CODE (SSA_NAME_VAR (orig)) == MEMORY_PARTITION_TAG)
-    return (TREE_CODE (dest) == SSA_NAME
-            && !is_gimple_reg (dest)
-           && (SSA_NAME_VAR (dest) == SSA_NAME_VAR (orig)
-                || bitmap_bit_p (MPT_SYMBOLS (SSA_NAME_VAR (orig)),
-                                DECL_UID (SSA_NAME_VAR (dest)))));
   
   /* Do not copy between types for which we *do* need a conversion.  */
   if (!useless_type_conversion_p (type_d, type_o))
@@ -136,48 +118,21 @@ may_propagate_copy (tree dest, tree orig)
       && POINTER_TYPE_P (type_d)
       && POINTER_TYPE_P (type_o))
     {
-      tree mt_dest = symbol_mem_tag (SSA_NAME_VAR (dest));
-      tree mt_orig = symbol_mem_tag (SSA_NAME_VAR (orig));
-      if (mt_dest && mt_orig && mt_dest != mt_orig)
-       return false;
-      else if (get_alias_set (TREE_TYPE (type_d)) != 
-              get_alias_set (TREE_TYPE (type_o)))
+      if (get_alias_set (TREE_TYPE (type_d))
+         != get_alias_set (TREE_TYPE (type_o)))
        return false;
-      else if (!MTAG_P (SSA_NAME_VAR (dest))
-              && !MTAG_P (SSA_NAME_VAR (orig))
-              && (DECL_NO_TBAA_P (SSA_NAME_VAR (dest))
-                  != DECL_NO_TBAA_P (SSA_NAME_VAR (orig))))
+      else if (DECL_NO_TBAA_P (SSA_NAME_VAR (dest))
+              != DECL_NO_TBAA_P (SSA_NAME_VAR (orig)))
        return false;
-
-      /* Also verify flow-sensitive information is compatible.  */
-      if (SSA_NAME_PTR_INFO (orig) && SSA_NAME_PTR_INFO (dest))
-       {
-         struct ptr_info_def *orig_ptr_info = SSA_NAME_PTR_INFO (orig);
-         struct ptr_info_def *dest_ptr_info = SSA_NAME_PTR_INFO (dest);
-
-         if (orig_ptr_info->name_mem_tag
-             && dest_ptr_info->name_mem_tag
-             && orig_ptr_info->pt_vars
-             && dest_ptr_info->pt_vars
-             && !bitmap_intersect_p (dest_ptr_info->pt_vars,
-                                     orig_ptr_info->pt_vars))
-           return false;
-       }
     }
 
-  /* If the destination is a SSA_NAME for a virtual operand, then we have
-     some special cases to handle.  */
+  /* Propagating virtual operands is always ok.  */
   if (TREE_CODE (dest) == SSA_NAME && !is_gimple_reg (dest))
     {
-      /* If both operands are SSA_NAMEs referring to virtual operands, then
-        we can always propagate.  */
-      if (TREE_CODE (orig) == SSA_NAME
-         && !is_gimple_reg (orig))
-       return true;
-
-      /* We have a "copy" from something like a constant into a virtual
-        operand.  Reject these.  */
-      return false;
+      /* But only between virtual operands.  */
+      gcc_assert (TREE_CODE (orig) == SSA_NAME && !is_gimple_reg (orig));
+
+      return true;
     }
 
   /* Anything else is OK.  */
@@ -211,8 +166,7 @@ may_propagate_copy_into_stmt (gimple dest, tree orig)
      is much simpler.  */
 
   if (TREE_CODE (orig) == SSA_NAME
-      && (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (orig)
-          ||  TREE_CODE (SSA_NAME_VAR (orig)) == MEMORY_PARTITION_TAG))
+      && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (orig))
     return false;
 
   if (is_gimple_assign (dest))
@@ -252,29 +206,13 @@ may_propagate_copy_into_asm (tree dest)
 void
 merge_alias_info (tree orig_name, tree new_name)
 {
-  tree new_sym = SSA_NAME_VAR (new_name);
-  tree orig_sym = SSA_NAME_VAR (orig_name);
-  var_ann_t new_ann = var_ann (new_sym);
-  var_ann_t orig_ann = var_ann (orig_sym);
-
-  /* No merging necessary when memory partitions are involved.  */
-  if (factoring_name_p (new_name))
-    {
-      gcc_assert (!is_gimple_reg (orig_sym));
-      return;
-    }
-  else if (factoring_name_p (orig_name))
-    {
-      gcc_assert (!is_gimple_reg (new_sym));
-      return;
-    }
-
   gcc_assert (POINTER_TYPE_P (TREE_TYPE (orig_name))
              && POINTER_TYPE_P (TREE_TYPE (new_name)));
 
 #if defined ENABLE_CHECKING
   gcc_assert (useless_type_conversion_p (TREE_TYPE (orig_name),
-                                       TREE_TYPE (new_name)));
+                                        TREE_TYPE (new_name)));
+#endif
 
   /* Check that flow-sensitive information is compatible.  Notice that
      we may not merge flow-sensitive information here.  This function
@@ -290,58 +228,12 @@ merge_alias_info (tree orig_name, tree new_name)
      same in every block dominated by the predicate.
 
      Since we cannot distinguish one case from another in this
-     function, we can only make sure that if P_i and Q_j have
-     flow-sensitive information, they should be compatible.
-
-     As callers of merge_alias_info are supposed to call may_propagate_copy
-     first, the following check is redundant.  Thus, only do it if checking
-     is enabled.  */
-  if (SSA_NAME_PTR_INFO (orig_name) && SSA_NAME_PTR_INFO (new_name))
-    {
-      struct ptr_info_def *orig_ptr_info = SSA_NAME_PTR_INFO (orig_name);
-      struct ptr_info_def *new_ptr_info = SSA_NAME_PTR_INFO (new_name);
-
-      /* Note that pointer NEW and ORIG may actually have different
-        pointed-to variables (e.g., PR 18291 represented in
-        testsuite/gcc.c-torture/compile/pr18291.c).  However, since
-        NEW is being copy-propagated into ORIG, it must always be
-        true that the pointed-to set for pointer NEW is the same, or
-        a subset, of the pointed-to set for pointer ORIG.  If this
-        isn't the case, we shouldn't have been able to do the
-        propagation of NEW into ORIG.  */
-      if (orig_ptr_info->name_mem_tag
-         && new_ptr_info->name_mem_tag
-         && orig_ptr_info->pt_vars
-         && new_ptr_info->pt_vars)
-       gcc_assert (bitmap_intersect_p (new_ptr_info->pt_vars,
-                                       orig_ptr_info->pt_vars));
-    }
-#endif
+     function, we cannot merge flow-sensitive information by
+     intersecting.  Instead the only thing we can do is to _not_
+     merge flow-sensitive information.
 
-  /* Synchronize the symbol tags.  If both pointers had a tag and they
-     are different, then something has gone wrong.  Symbol tags can
-     always be merged because they are flow insensitive, all the SSA
-     names of the same base DECL share the same symbol tag.  */
-  if (new_ann->symbol_mem_tag == NULL_TREE)
-    new_ann->symbol_mem_tag = orig_ann->symbol_mem_tag;
-  else if (orig_ann->symbol_mem_tag == NULL_TREE)
-    orig_ann->symbol_mem_tag = new_ann->symbol_mem_tag;
-  else
-    gcc_assert (new_ann->symbol_mem_tag == orig_ann->symbol_mem_tag);
-
-  /* Copy flow-sensitive alias information in case that NEW_NAME
-     didn't get a NMT but was set to pt_anything for optimization
-     purposes.  In case ORIG_NAME has a NMT we can safely use its
-     flow-sensitive alias information as a conservative estimate.  */
-  if (SSA_NAME_PTR_INFO (orig_name)
-      && SSA_NAME_PTR_INFO (orig_name)->name_mem_tag
-      && (!SSA_NAME_PTR_INFO (new_name)
-         || !SSA_NAME_PTR_INFO (new_name)->name_mem_tag))
-    {
-      struct ptr_info_def *orig_ptr_info = SSA_NAME_PTR_INFO (orig_name);
-      struct ptr_info_def *new_ptr_info = get_ptr_info (new_name);
-      memcpy (new_ptr_info, orig_ptr_info, sizeof (struct ptr_info_def));
-    }
+     ???  At some point we should enhance this machinery to distinguish
+     both cases in the caller.  */
 }
 
 
@@ -464,8 +356,7 @@ propagate_tree_value_into_stmt (gimple_stmt_iterator *gsi, tree val)
 
       tree expr = NULL_TREE;
       propagate_tree_value (&expr, val);
-      new_stmt  = gimple_build_assign (gimple_call_lhs (stmt), expr);
-      copy_virtual_operands (new_stmt, stmt);
+      new_stmt = gimple_build_assign (gimple_call_lhs (stmt), expr);
       move_ssa_defining_stmt_for_defs (new_stmt, stmt);
       gsi_replace (gsi, new_stmt, false);
     }
@@ -513,7 +404,7 @@ stmt_may_generate_copy (gimple stmt)
     return false;
 
   /* Statements with loads and/or stores will never generate a useful copy.  */
-  if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
+  if (gimple_vuse (stmt))
     return false;
 
   /* Otherwise, the only statements that generate useful copies are
@@ -864,8 +755,10 @@ copy_prop_visit_phi_node (gimple phi)
         Otherwise, this may move loop variant variables outside of
         their loops and prevent coalescing opportunities.  If the
         value was loop invariant, it will be hoisted by LICM and
-        exposed for copy propagation.  */
-      if (loop_depth_of_name (arg) > loop_depth_of_name (lhs))
+        exposed for copy propagation.  Not a problem for virtual
+        operands though.  */
+      if (is_gimple_reg (lhs)
+         && loop_depth_of_name (arg) > loop_depth_of_name (lhs))
        {
          phi_val.value = lhs;
          break;
index d30e237..e89824f 100644 (file)
@@ -115,7 +115,6 @@ copy_rename_partition_coalesce (var_map map, tree var1, tree var2, FILE *debug)
   int p1, p2, p3;
   tree root1, root2;
   tree rep1, rep2;
-  var_ann_t ann1, ann2, ann3;
   bool ign1, ign2, abnorm;
 
   gcc_assert (TREE_CODE (var1) == SSA_NAME);
@@ -144,9 +143,6 @@ copy_rename_partition_coalesce (var_map map, tree var1, tree var2, FILE *debug)
   root1 = SSA_NAME_VAR (rep1);
   root2 = SSA_NAME_VAR (rep2);
 
-  ann1 = var_ann (root1);
-  ann2 = var_ann (root2);
-
   if (p1 == p2)
     {
       if (debug)
@@ -207,16 +203,6 @@ copy_rename_partition_coalesce (var_map map, tree var1, tree var2, FILE *debug)
        }
     }
 
-  /* Don't coalesce if there are two different memory tags.  */
-  if (ann1->symbol_mem_tag
-      && ann2->symbol_mem_tag
-      && ann1->symbol_mem_tag != ann2->symbol_mem_tag)
-    {
-      if (debug)
-       fprintf (debug, " : 2 memory tags. No coalesce.\n");
-      return false;
-    }
-
   /* If both values have default defs, we can't coalesce.  If only one has a 
      tag, make sure that variable is the new root partition.  */
   if (gimple_default_def (cfun, root1))
@@ -252,8 +238,7 @@ copy_rename_partition_coalesce (var_map map, tree var1, tree var2, FILE *debug)
       && POINTER_TYPE_P (TREE_TYPE (root2))
       && ((get_alias_set (TREE_TYPE (TREE_TYPE (root1)))
           != get_alias_set (TREE_TYPE (TREE_TYPE (root2))))
-         || ((DECL_P (root1) && !MTAG_P (root1))
-             && (DECL_P (root2) && !MTAG_P (root2))
+         || (DECL_P (root1) && DECL_P (root2)
              && DECL_NO_TBAA_P (root1) != DECL_NO_TBAA_P (root2))))
     {
       if (debug)
@@ -272,13 +257,6 @@ copy_rename_partition_coalesce (var_map map, tree var1, tree var2, FILE *debug)
   else if (!ign1)
     replace_ssa_name_symbol (partition_to_var (map, p3), root1);
 
-  /* Update the various flag widgitry of the current base representative.  */
-  ann3 = var_ann (SSA_NAME_VAR (partition_to_var (map, p3)));
-  if (ann1->symbol_mem_tag)
-    ann3->symbol_mem_tag = ann1->symbol_mem_tag;
-  else
-    ann3->symbol_mem_tag = ann2->symbol_mem_tag;
-
   if (debug)
     {
       fprintf (debug, " --> P%d ", p3);
index 3c75046..0c20571 100644 (file)
@@ -233,7 +233,12 @@ mark_operand_necessary (tree op)
 
   ver = SSA_NAME_VERSION (op);
   if (TEST_BIT (processed, ver))
-    return;
+    {
+      stmt = SSA_NAME_DEF_STMT (op);
+      gcc_assert (gimple_nop_p (stmt)
+                 || gimple_plf (stmt, STMT_NECESSARY));
+      return;
+    }
   SET_BIT (processed, ver);
 
   stmt = SSA_NAME_DEF_STMT (op);
@@ -242,6 +247,14 @@ mark_operand_necessary (tree op)
   if (gimple_plf (stmt, STMT_NECESSARY) || gimple_nop_p (stmt))
     return;
 
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    {
+      fprintf (dump_file, "marking necessary through ");
+      print_generic_expr (dump_file, op, 0);
+      fprintf (dump_file, " stmt ");
+      print_gimple_stmt (dump_file, stmt, 0, 0);
+    }
+
   gimple_set_plf (stmt, STMT_NECESSARY, true);
   VEC_safe_push (gimple, heap, worklist, stmt);
 }
@@ -429,6 +442,133 @@ find_obviously_necessary_stmts (struct edge_list *el)
 }
 
 
+/* Return true if REF is based on an aliased base, otherwise false.  */
+
+static bool
+ref_may_be_aliased (tree ref)
+{
+  while (handled_component_p (ref))
+    ref = TREE_OPERAND (ref, 0);
+  return !(DECL_P (ref)
+          && !may_be_aliased (ref));
+}
+
+struct ref_data {
+  tree base;
+  HOST_WIDE_INT size;
+  HOST_WIDE_INT offset;
+  HOST_WIDE_INT max_size;
+};
+
+static bitmap visited = NULL;
+static unsigned int longest_chain = 0;
+static unsigned int total_chain = 0;
+static bool chain_ovfl = false;
+
+/* Worker for the walker that marks reaching definitions of REF,
+   which is based on a non-aliased decl, necessary.  It returns
+   true whenever the defining statement of the current VDEF is
+   a kill for REF, as no dominating may-defs are necessary for REF
+   anymore.  DATA points to cached get_ref_base_and_extent data for REF.  */
+
+static bool
+mark_aliased_reaching_defs_necessary_1 (tree ref, tree vdef, void *data)
+{
+  gimple def_stmt = SSA_NAME_DEF_STMT (vdef);
+  struct ref_data *refd = (struct ref_data *)data;
+
+  /* All stmts we visit are necessary.  */
+  mark_operand_necessary (vdef);
+
+  /* If the stmt lhs kills ref, then we can stop walking.  */
+  if (gimple_has_lhs (def_stmt)
+      && TREE_CODE (gimple_get_lhs (def_stmt)) != SSA_NAME)
+    {
+      tree base, lhs = gimple_get_lhs (def_stmt);
+      HOST_WIDE_INT size, offset, max_size;
+      base = get_ref_base_and_extent (lhs, &offset, &size, &max_size);
+      /* We can get MEM[symbol: sZ, index: D.8862_1] here,
+        so base == refd->base does not always hold.  */
+      if (base == refd->base)
+       {
+         /* For a must-alias check we need to be able to constrain
+            the accesses properly.  */
+         if (size != -1 && size == max_size
+             && refd->max_size != -1)
+           {
+             if (offset <= refd->offset
+                 && offset + size >= refd->offset + refd->max_size)
+               return true;
+           }
+         /* Or they need to be exactly the same.  */
+         else if (operand_equal_p (ref, lhs, 0))
+           return true;
+       }
+    }
+
+  /* Otherwise keep walking.  */
+  return false;
+}
+
+static void
+mark_aliased_reaching_defs_necessary (gimple stmt, tree ref)
+{
+  struct ref_data refd;
+  unsigned int chain;
+  gcc_assert (!chain_ovfl);
+  refd.base = get_ref_base_and_extent (ref, &refd.offset, &refd.size,
+                                      &refd.max_size);
+  chain = walk_aliased_vdefs (ref, gimple_vuse (stmt),
+                             mark_aliased_reaching_defs_necessary_1,
+                             &refd, NULL);
+  if (chain > longest_chain)
+    longest_chain = chain;
+  total_chain += chain;
+}
+
+/* Worker for the walker that marks reaching definitions of REF, which
+   is not based on a non-aliased decl.  For simplicity we need to end
+   up marking all may-defs necessary that are not based on a non-aliased
+   decl.  The only job of this walker is to skip may-defs based on
+   a non-aliased decl.  */
+
+static bool
+mark_all_reaching_defs_necessary_1 (tree ref ATTRIBUTE_UNUSED,
+                               tree vdef, void *data ATTRIBUTE_UNUSED)
+{
+  gimple def_stmt = SSA_NAME_DEF_STMT (vdef);
+
+  /* We have to skip already visited (and thus necessary) statements
+     to make the chaining work after we dropped back to simple mode.  */
+  if (chain_ovfl
+      && TEST_BIT (processed, SSA_NAME_VERSION (vdef)))
+    {
+      gcc_assert (gimple_nop_p (def_stmt)
+                 || gimple_plf (def_stmt, STMT_NECESSARY));
+      return false;
+    }
+
+  /* We want to skip stores to non-aliased variables.  */
+  if (!chain_ovfl
+      && gimple_assign_single_p (def_stmt))
+    {
+      tree lhs = gimple_assign_lhs (def_stmt);
+      if (!ref_may_be_aliased (lhs))
+       return false;
+    }
+
+  /* But can stop after the first necessary statement.  */
+  mark_operand_necessary (vdef);
+  return true;
+}
+
+static void
+mark_all_reaching_defs_necessary (gimple stmt)
+{
+  walk_aliased_vdefs (NULL, gimple_vuse (stmt),
+                     mark_all_reaching_defs_necessary_1, NULL, &visited);
+}
+
 /* Propagate necessity using the operands of necessary statements.
    Process the uses on each statement in the worklist, and add all
    feeding statements which contribute to the calculation of this
@@ -471,7 +611,10 @@ propagate_necessity (struct edge_list *el)
            }
        }
 
-      if (gimple_code (stmt) == GIMPLE_PHI)
+      if (gimple_code (stmt) == GIMPLE_PHI
+         /* We do not process virtual PHI nodes nor do we track their
+            necessity.  */
+         && is_gimple_reg (gimple_phi_result (stmt)))
        {
          /* PHI nodes are somewhat special in that each PHI alternative has
             data and control dependencies.  All the statements feeding the
@@ -506,16 +649,121 @@ propagate_necessity (struct edge_list *el)
        {
          /* Propagate through the operands.  Examine all the USE, VUSE and
             VDEF operands in this statement.  Mark all the statements 
-            which feed this statement's uses as necessary.  The
-            operands of VDEF expressions are also needed as they
-            represent potential definitions that may reach this
-            statement (VDEF operands allow us to follow def-def
-            links).  */
+            which feed this statement's uses as necessary.  */
          ssa_op_iter iter;
          tree use;
 
-         FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_ALL_USES)
+         FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
            mark_operand_necessary (use);
+
+         use = gimple_vuse (stmt);
+         if (!use)
+           continue;
+
+         /* If we dropped to simple mode make all immediately
+            reachable definitions necessary.  */
+         if (chain_ovfl)
+           {
+             mark_all_reaching_defs_necessary (stmt);
+             continue;
+           }
+
+         /* For statements that may load from memory (have a VUSE) we
+            have to mark all reaching (may-)definitions as necessary.
+            We partition this task into two cases:
+             1) explicit loads based on decls that are not aliased
+             2) implicit loads (like calls) and explicit loads not
+                based on decls that are not aliased (like indirect
+                references or loads from globals)
+            For 1) we mark all reaching may-defs as necessary, stopping
+            at dominating kills.  For 2) we want to mark all dominating
+            references necessary, but non-aliased ones which we handle
+            in 1).  Instead of doing so for each load we rely on the
+            worklist to eventually reach all dominating references and
+            instead just mark the immediately dominating references
+            as necessary (but skipping non-aliased ones).  */
+
+         if (is_gimple_call (stmt))
+           {
+             unsigned i;
+
+             /* Calls implicitly load from memory, their arguments
+                in addition may explicitly perform memory loads.
+                This also ensures propagation for case 2 for stores.  */
+             mark_all_reaching_defs_necessary (stmt);
+             for (i = 0; i < gimple_call_num_args (stmt); ++i)
+               {
+                 tree arg = gimple_call_arg (stmt, i);
+                 if (TREE_CODE (arg) == SSA_NAME
+                     || is_gimple_min_invariant (arg))
+                   continue;
+                 if (!ref_may_be_aliased (arg))
+                   mark_aliased_reaching_defs_necessary (stmt, arg);
+               }
+           }
+         else if (gimple_assign_single_p (stmt))
+           {
+             tree lhs, rhs;
+             bool rhs_aliased = false;
+             /* If this is a load mark things necessary.  */
+             rhs = gimple_assign_rhs1 (stmt);
+             if (TREE_CODE (rhs) != SSA_NAME
+                 && !is_gimple_min_invariant (rhs))
+               {
+                 if (!ref_may_be_aliased (rhs))
+                   mark_aliased_reaching_defs_necessary (stmt, rhs);
+                 else
+                   rhs_aliased = true;
+               }
+             /* If this is an aliased store, mark things necessary.
+                This is where we make sure to propagate for case 2.  */
+             lhs = gimple_assign_lhs (stmt);
+             if (rhs_aliased
+                 || (TREE_CODE (lhs) != SSA_NAME
+                     && ref_may_be_aliased (lhs)))
+               mark_all_reaching_defs_necessary (stmt);
+           }
+         else if (gimple_code (stmt) == GIMPLE_RETURN)
+           {
+             tree rhs = gimple_return_retval (stmt);
+             /* A return statement may perform a load.  */
+             if (TREE_CODE (rhs) != SSA_NAME
+                 && !is_gimple_min_invariant (rhs))
+               {
+                 if (!ref_may_be_aliased (rhs))
+                   mark_aliased_reaching_defs_necessary (stmt, rhs);
+                 else
+                   mark_all_reaching_defs_necessary (stmt);
+               }
+           }
+         else if (gimple_code (stmt) == GIMPLE_ASM)
+           {
+             unsigned i;
+             mark_all_reaching_defs_necessary (stmt);
+             /* Inputs may perform loads.  */
+             for (i = 0; i < gimple_asm_ninputs (stmt); ++i)
+               {
+                 tree op = TREE_VALUE (gimple_asm_input_op (stmt, i));
+                 if (TREE_CODE (op) != SSA_NAME
+                     && !is_gimple_min_invariant (op)
+                     && !ref_may_be_aliased (op))
+                   mark_aliased_reaching_defs_necessary (stmt, op);
+               }
+           }
+         else
+           gcc_unreachable ();
+
+         /* If we over-used our alias oracle budget drop to simple
+            mode.  The cost metric allows quadratic behavior up to
+            a constant maximal chain and after that falls back to
+            super-linear complexity.  */
+         if (longest_chain > 256
+             && total_chain > 256 * longest_chain)
+           {
+             chain_ovfl = true;
+             if (visited)
+               bitmap_clear (visited);
+           }
        }
     }
 }
@@ -537,6 +785,40 @@ remove_dead_phis (basic_block bb)
       stats.total_phis++;
       phi = gsi_stmt (gsi);
 
+      /* We do not track necessity of virtual PHI nodes.  Instead do
+         very simple dead PHI removal here.  */
+      if (!is_gimple_reg (gimple_phi_result (phi)))
+       {
+         unsigned i;
+         tree vuse;
+
+         /* Virtual PHI nodes with one or identical arguments
+            can be removed.  */
+         vuse = gimple_phi_arg_def (phi, 0);
+         for (i = 1; i < gimple_phi_num_args (phi); ++i)
+           {
+             if (gimple_phi_arg_def (phi, i) != vuse)
+               {
+                 vuse = NULL_TREE;
+                 break;
+               }
+           }
+         if (vuse != NULL_TREE)
+           {
+             tree vdef = gimple_phi_result (phi);
+             use_operand_p use_p;
+             imm_use_iterator iter;
+             gimple use_stmt;
+             FOR_EACH_IMM_USE_STMT (use_stmt, iter, vdef)
+               FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
+                 SET_USE (use_p, vuse);
+             if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (vdef))
+               SSA_NAME_OCCURS_IN_ABNORMAL_PHI (vuse) = 1;
+           }
+         else
+           gimple_set_plf (phi, STMT_NECESSARY, true);
+       }
+
       if (!gimple_plf (phi, STMT_NECESSARY))
        {
          something_changed = true;
@@ -549,11 +831,10 @@ remove_dead_phis (basic_block bb)
 
          remove_phi_node (&gsi, true);
          stats.removed_phis++;
+         continue;
        }
-      else
-       {
-          gsi_next (&gsi);
-       }
+
+      gsi_next (&gsi);
     }
   return something_changed;
 }
@@ -643,7 +924,8 @@ remove_dead_stmt (gimple_stmt_iterator *i, basic_block bb)
           remove_edge (EDGE_SUCC (bb, 1));
        }
     }
-  
+
+  unlink_stmt_vdef (stmt);
   gsi_remove (i, true);  
   release_defs (stmt); 
 }
@@ -665,11 +947,6 @@ eliminate_unnecessary_stmts (void)
     fprintf (dump_file, "\nEliminating unnecessary statements:\n");
 
   clear_special_calls ();
-  FOR_EACH_BB (bb)
-    {
-      /* Remove dead PHI nodes.  */
-      something_changed |= remove_dead_phis (bb);
-    }
 
   FOR_EACH_BB (bb)
     {
@@ -692,7 +969,6 @@ eliminate_unnecessary_stmts (void)
              if (call)
                {
                  tree name;
-                 gimple g;
 
                  /* When LHS of var = call (); is dead, simplify it into
                     call (); saving one operand.  */
@@ -709,11 +985,8 @@ eliminate_unnecessary_stmts (void)
                        }
                      
                      push_stmt_changes (gsi_stmt_ptr (&gsi));
-                     g = gimple_copy (stmt);
-                     gimple_call_set_lhs (g, NULL_TREE);
-                     gsi_replace (&gsi, g, false);
-                     maybe_clean_or_replace_eh_stmt (stmt, g);
-                     mark_symbols_for_renaming (g);
+                     gimple_call_set_lhs (stmt, NULL_TREE);
+                     maybe_clean_or_replace_eh_stmt (stmt, stmt);
                      pop_stmt_changes (gsi_stmt_ptr (&gsi));
                      release_ssa_name (name);
                    }
@@ -728,6 +1001,12 @@ eliminate_unnecessary_stmts (void)
        }
     }
 
+  FOR_EACH_BB (bb)
+    {
+      /* Remove dead PHI nodes.  */
+      something_changed |= remove_dead_phis (bb);
+    }
+
   return something_changed;
 }
 
@@ -839,7 +1118,11 @@ perform_tree_ssa_dce (bool aggressive)
 
   find_obviously_necessary_stmts (el);
 
+  longest_chain = 0;
+  total_chain = 0;
+  chain_ovfl = false;
   propagate_necessity (el);
+  BITMAP_FREE (visited);
 
   something_changed |= eliminate_unnecessary_stmts ();
   something_changed |= cfg_altered;
index c252a72..e2909e8 100644 (file)
@@ -134,10 +134,6 @@ static VEC(expr_hash_elt_t,heap) *avail_exprs_stack;
    expressions are removed from AVAIL_EXPRS.  Else we may change the
    hash code for an expression and be unable to find/remove it from
    AVAIL_EXPRS.  */
-typedef gimple *gimple_p;
-DEF_VEC_P(gimple_p);
-DEF_VEC_ALLOC_P(gimple_p,heap);
-
 static VEC(gimple_p,heap) *stmts_to_rescan;
 
 /* Structure for entries in the expression hash table.  */
@@ -1841,7 +1837,7 @@ eliminate_redundant_computations (gimple_stmt_iterator* gsi)
   if (! def
       || TREE_CODE (def) != SSA_NAME
       || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (def)
-      || !ZERO_SSA_OPERANDS (stmt, SSA_OP_VDEF)
+      || gimple_vdef (stmt)
       /* Do not record equivalences for increments of ivs.  This would create
         overlapping live ranges for a very questionable gain.  */
       || simple_iv_increment_p (stmt))
@@ -2021,7 +2017,7 @@ record_equivalences_from_stmt (gimple stmt, int may_optimize_p)
       else
         new_stmt = gimple_build_assign (rhs, lhs);
 
-      create_ssa_artificial_load_stmt (new_stmt, stmt, true);
+      gimple_set_vuse (new_stmt, gimple_vdef (stmt));
 
       /* Finally enter the statement into the available expression
         table.  */
@@ -2405,7 +2401,6 @@ avail_expr_hash (const void *p)
   gimple stmt = ((const struct expr_hash_elt *)p)->stmt;
   const struct hashable_expr *expr = &((const struct expr_hash_elt *)p)->expr;
   tree vuse;
-  ssa_op_iter iter;
   hashval_t val = 0;
 
   val = iterative_hash_hashable_expr (expr, val);
@@ -2416,11 +2411,11 @@ avail_expr_hash (const void *p)
   if (!stmt)
     return val;
 
-  /* Add the SSA version numbers of every vuse operand.  This is important
+  /* Add the SSA version numbers of the 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.  */
-  FOR_EACH_SSA_TREE_OPERAND (vuse, stmt, iter, SSA_OP_VUSE)
+  if ((vuse = gimple_vuse (stmt)))
     val = iterative_hash_expr (vuse, val);
 
   return val;
@@ -2462,8 +2457,8 @@ avail_expr_eq (const void *p1, const void *p2)
       && types_compatible_p (expr1->type, expr2->type))
     {
       /* Note that STMT1 and/or STMT2 may be NULL.  */
-      bool ret = compare_ssa_operands_equal (stmt1, stmt2, SSA_OP_VUSE);
-      return ret;
+      return ((stmt1 ? gimple_vuse (stmt1) : NULL_TREE)
+             == (stmt2 ? gimple_vuse (stmt2) : NULL_TREE));
     }
 
   return false;
index a340c5e..315b550 100644 (file)
@@ -84,13 +84,6 @@ struct dse_block_local_data
   bitmap stores;
 };
 
-/* Basic blocks of the potentially dead store and the following
-   store, for memory_address_same.  */
-struct address_walk_data
-{
-  basic_block store1_bb, store2_bb;
-};
-
 static bool gate_dse (void);
 static unsigned int tree_ssa_dse (void);
 static void dse_initialize_block_local_data (struct dom_walk_data *,
@@ -151,218 +144,112 @@ dse_initialize_block_local_data (struct dom_walk_data *walk_data,
     }
 }
 
-/* Helper function for memory_address_same via walk_tree.  Returns
-   non-NULL if it finds an SSA_NAME which is part of the address,
-   such that the definition of the SSA_NAME post-dominates the store
-   we want to delete but not the store that we believe makes it
-   redundant.  This indicates that the address may change between
-   the two stores.  */
-
-static tree
-memory_ssa_name_same (tree *expr_p, int *walk_subtrees ATTRIBUTE_UNUSED,
-                     void *data)
-{
-  struct address_walk_data *walk_data = (struct address_walk_data *) data;
-  tree expr = *expr_p;
-  gimple def_stmt;
-  basic_block def_bb;
-
-  if (TREE_CODE (expr) != SSA_NAME)
-    return NULL_TREE;
-
-  /* If we've found a default definition, then there's no problem.  Both
-     stores will post-dominate it.  And def_bb will be NULL.  */
-  if (SSA_NAME_IS_DEFAULT_DEF (expr))
-    return NULL_TREE;
-
-  def_stmt = SSA_NAME_DEF_STMT (expr);
-  def_bb = gimple_bb (def_stmt);
-
-  /* DEF_STMT must dominate both stores.  So if it is in the same
-     basic block as one, it does not post-dominate that store.  */
-  if (walk_data->store1_bb != def_bb
-      && dominated_by_p (CDI_POST_DOMINATORS, walk_data->store1_bb, def_bb))
-    {
-      if (walk_data->store2_bb == def_bb
-         || !dominated_by_p (CDI_POST_DOMINATORS, walk_data->store2_bb,
-                             def_bb))
-       /* Return non-NULL to stop the walk.  */
-       return *expr_p;
-    }
-
-  return NULL_TREE;
-}
-
-/* Return TRUE if the destination memory address in STORE1 and STORE2
-   might be modified after STORE1, before control reaches STORE2.  */
-
-static bool
-memory_address_same (gimple store1, gimple store2)
-{
-  struct address_walk_data walk_data;
-
-  walk_data.store1_bb = gimple_bb (store1);
-  walk_data.store2_bb = gimple_bb (store2);
-
-  return (walk_tree (gimple_assign_lhs_ptr (store1), memory_ssa_name_same,
-                    &walk_data, NULL)
-         == NULL);
-}
-
-/* Return true if there is a stmt that kills the lhs of STMT and is in the
-   virtual def-use chain of STMT without a use in between the kill and STMT.
-   Returns false if no such stmt is found.
-   *FIRST_USE_P is set to the first use of the single virtual def of
-   STMT.  *USE_P is set to the vop killed by *USE_STMT.  */
-
-static bool
-get_kill_of_stmt_lhs (gimple stmt,
-                     use_operand_p * first_use_p,
-                     use_operand_p * use_p, gimple * use_stmt)
-{
-  tree lhs;
-
-  gcc_assert (is_gimple_assign (stmt));
-
-  lhs = gimple_assign_lhs (stmt);
-
-  /* We now walk the chain of single uses of the single VDEFs.
-     We succeeded finding a kill if the lhs of the use stmt is
-     equal to the original lhs.  We can keep walking to the next
-     use if there are no possible uses of the original lhs in
-     the stmt.  */
-  do
-    {
-      tree use_lhs;
-      def_operand_p def_p;
-
-      /* The stmt must have a single VDEF.  */
-      def_p = SINGLE_SSA_DEF_OPERAND (stmt, SSA_OP_VDEF);
-      if (def_p == NULL_DEF_OPERAND_P)
-       return false;
-
-      /* Get the single immediate use of the def.  */
-      if (!single_imm_use (DEF_FROM_PTR (def_p), first_use_p, &stmt))
-       return false;
-      first_use_p = use_p;
-
-      /* If there are possible hidden uses, give up.  */
-      if (!gimple_assign_single_p (stmt)
-         || (TREE_CODE (gimple_assign_rhs1 (stmt)) != SSA_NAME
-             && !is_gimple_min_invariant (gimple_assign_rhs1 (stmt))))
-       return false;
-
-      /* If the use stmts lhs matches the original lhs we have
-        found the kill, otherwise continue walking.  */
-      use_lhs = gimple_assign_lhs (stmt);
-      if (operand_equal_p (use_lhs, lhs, 0))
-       {
-         *use_stmt = stmt;
-         return true;
-       }
-    }
-  while (1);
-}
-
 /* A helper of dse_optimize_stmt.
-   Given a GIMPLE_ASSIGN in STMT, check that each VDEF has one
-   use, and that one use is another VDEF clobbering the first one.
-
+   Given a GIMPLE_ASSIGN in STMT, find a candidate statement *USE_STMT that
+   may prove STMT to be dead.
    Return TRUE if the above conditions are met, otherwise FALSE.  */
 
 static bool
-dse_possible_dead_store_p (gimple stmt,
-                          use_operand_p *first_use_p,
-                          use_operand_p *use_p,
-                          gimple *use_stmt,
-                          struct dse_global_data *dse_gd,
-                          struct dse_block_local_data *bd)
+dse_possible_dead_store_p (gimple stmt, gimple *use_stmt)
 {
-  ssa_op_iter op_iter;
-  bool fail = false;
-  def_operand_p var1;
-  vuse_vec_p vv;
-  tree defvar = NULL_TREE;
-  tree prev_defvar = NULL_TREE;
   gimple temp;
+  unsigned cnt = 0;
 
-  /* We want to verify that each virtual definition in STMT has
-     precisely one use and that all the virtual definitions are
-     used by the same single statement.  When complete, we
-     want USE_STMT to refer to the one statement which uses
-     all of the virtual definitions from STMT.  */
   *use_stmt = NULL;
-  FOR_EACH_SSA_VDEF_OPERAND (var1, vv, stmt, op_iter)
-    {
-      defvar = DEF_FROM_PTR (var1);
-
-      /* If this virtual def does not have precisely one use, then
-        we will not be able to eliminate STMT.  */
-      if (!has_single_use (defvar))
-       {
-         fail = true;
-         break;
-       }
 
-      /* Get the one and only immediate use of DEFVAR.  */
-      single_imm_use (defvar, use_p, &temp);
-      gcc_assert (*use_p != NULL_USE_OPERAND_P);
-      *first_use_p = *use_p;
+  /* Find the first dominated statement that clobbers (part of) the
+     memory stmt stores to with no intermediate statement that may use
+     part of the memory stmt stores.  That is, find a store that may
+     prove stmt to be a dead store.  */
+  temp = stmt;
+  do
+    {
+      gimple prev, use_stmt;
+      imm_use_iterator ui;
+      bool fail = false;
+      tree defvar;
+
+      /* Limit stmt walking to be linear in the number of possibly
+         dead stores.  */
+      if (++cnt > 256)
+       return false;
 
-      /* ???  If we hit a GIMPLE_PHI we could skip to the PHI_RESULT uses.
-        Don't bother to do that for now.  */
       if (gimple_code (temp) == GIMPLE_PHI)
+       defvar = PHI_RESULT (temp);
+      else
+       defvar = gimple_vdef (temp);
+      prev = temp;
+      temp = NULL;
+      FOR_EACH_IMM_USE_STMT (use_stmt, ui, defvar)
        {
-         fail = true;
-         break;
-       }
-
-      /* In the case of memory partitions, we may get:
+         cnt++;
 
-          # MPT.764_162 = VDEF <MPT.764_161(D)>
-          x = {};
-          # MPT.764_167 = VDEF <MPT.764_162>
-          y = {};
-
-          So we must make sure we're talking about the same LHS.
-      */
-      if (is_gimple_assign (temp))
-       {
-         tree base1 = get_base_address (gimple_assign_lhs (stmt));
-         tree base2 = get_base_address (gimple_assign_lhs (temp));
-
-         while (base1 && INDIRECT_REF_P (base1))
-           base1 = TREE_OPERAND (base1, 0);
-         while (base2 && INDIRECT_REF_P (base2))
-           base2 = TREE_OPERAND (base2, 0);
-
-         if (base1 != base2)
+         /* In simple cases we can look through PHI nodes, but we
+            have to be careful with loops and with memory references
+            containing operands that are also operands of PHI nodes.
+            See gcc.c-torture/execute/20051110-*.c.  */
+         if (gimple_code (use_stmt) == GIMPLE_PHI)
+           {
+             if (temp
+                 /* We can look through PHIs to post-dominated regions
+                    without worrying if the use not also dominates prev
+                    (in which case it would be a loop PHI with the use
+                    in a latch block).  */
+                 || gimple_bb (prev) == gimple_bb (use_stmt)
+                 || !dominated_by_p (CDI_POST_DOMINATORS,
+                                     gimple_bb (prev), gimple_bb (use_stmt))
+                 || dominated_by_p (CDI_DOMINATORS,
+                                    gimple_bb (prev), gimple_bb (use_stmt)))
+               {
+                 fail = true;
+                 BREAK_FROM_IMM_USE_STMT (ui);
+               }
+             temp = use_stmt;
+           }
+         /* If the statement is a use the store is not dead.  */
+         else if (ref_maybe_used_by_stmt_p (use_stmt,
+                                            gimple_assign_lhs (stmt)))
            {
              fail = true;
-             break;
+             BREAK_FROM_IMM_USE_STMT (ui);
+           }
+         /* If this is a store, remember it or bail out if we have
+            multiple ones (the will be in different CFG parts then).  */
+         else if (gimple_vdef (use_stmt))
+           {
+             if (temp)
+               {
+                 fail = true;
+                 BREAK_FROM_IMM_USE_STMT (ui);
+               }
+             temp = use_stmt;
            }
        }
 
-      /* If the immediate use of DEF_VAR is not the same as the
-        previously find immediate uses, then we will not be able
-        to eliminate STMT.  */
-      if (*use_stmt == NULL)
-       {
-         *use_stmt = temp;
-         prev_defvar = defvar;
-       }
-      else if (temp != *use_stmt)
+      if (fail)
+       return false;
+
+      /* If we didn't find any definition this means the store is dead
+         if it isn't a store to global reachable memory.  In this case
+        just pretend the stmt makes itself dead.  Otherwise fail.  */
+      if (!temp)
        {
-         fail = true;
+         if (is_hidden_global_store (stmt))
+           return false;
+
+         temp = stmt;
          break;
        }
     }
+  /* We deliberately stop on clobbering statements and not only on
+     killing ones to make walking cheaper.  Otherwise we can just
+     continue walking until both stores have equal reference trees.  */
+  while (!stmt_may_clobber_ref_p (temp, gimple_assign_lhs (stmt)));
 
-  if (fail)
-    {
-      record_voperand_set (dse_gd->stores, &bd->stores, gimple_uid (stmt));
-      return false;
-    }
+  if (!is_gimple_assign (temp))
+    return false;
+
+  *use_stmt = temp;
 
   return true;
 }
@@ -393,7 +280,7 @@ dse_optimize_stmt (struct dom_walk_data *walk_data,
 
   /* If this statement has no virtual defs, then there is nothing
      to do.  */
-  if (ZERO_SSA_OPERANDS (stmt, SSA_OP_VDEF))
+  if (!gimple_vdef (stmt))
     return;
 
   /* We know we have virtual definitions.  If this is a GIMPLE_ASSIGN
@@ -406,51 +293,21 @@ dse_optimize_stmt (struct dom_walk_data *walk_data,
 
   if (is_gimple_assign (stmt))
     {
-      use_operand_p first_use_p = NULL_USE_OPERAND_P;
-      use_operand_p use_p = NULL;
       gimple use_stmt;
 
-      if (!dse_possible_dead_store_p (stmt, &first_use_p, &use_p, &use_stmt, 
-                                     dse_gd, bd))
-       return;
+      record_voperand_set (dse_gd->stores, &bd->stores, gimple_uid (stmt));
 
-      /* If we have precisely one immediate use at this point, then we may
-        have found redundant store.  Make sure that the stores are to
-        the same memory location.  This includes checking that any
-        SSA-form variables in the address will have the same values.  */
-      if (use_p != NULL_USE_OPERAND_P
-          && bitmap_bit_p (dse_gd->stores, get_stmt_uid (use_stmt))
-          && !operand_equal_p (gimple_assign_lhs (stmt),
-                               gimple_assign_lhs (use_stmt), 0)
-          && memory_address_same (stmt, use_stmt))
-        {
-          /* If we have precisely one immediate use at this point, but
-             the stores are not to the same memory location then walk the
-             virtual def-use chain to get the stmt which stores to that same
-             memory location.  */
-          if (!get_kill_of_stmt_lhs (stmt, &first_use_p, &use_p, &use_stmt))
-            {
-              record_voperand_set (dse_gd->stores, &bd->stores, 
-                                  gimple_uid (stmt));
-              return;
-            }
-        }
+      if (!dse_possible_dead_store_p (stmt, &use_stmt))
+       return;
 
       /* If we have precisely one immediate use at this point and the
         stores are to the same memory location or there is a chain of
         virtual uses from stmt and the stmt which stores to that same
         memory location, then we may have found redundant store.  */
-      if (use_p != NULL_USE_OPERAND_P
-         && bitmap_bit_p (dse_gd->stores, get_stmt_uid (use_stmt))
+      if (bitmap_bit_p (dse_gd->stores, get_stmt_uid (use_stmt))
          && operand_equal_p (gimple_assign_lhs (stmt),
-                             gimple_assign_lhs (use_stmt), 0)
-         && memory_address_same (stmt, use_stmt))
+                             gimple_assign_lhs (use_stmt), 0))
        {
-         ssa_op_iter op_iter;
-         def_operand_p var1;
-         vuse_vec_p vv;
-         tree stmt_lhs;
-
          /* If use_stmt is or might be a nop assignment, e.g. for
             struct { ... } S a, b, *p; ...
             b = a; b = b;
@@ -462,14 +319,14 @@ dse_optimize_stmt (struct dom_walk_data *walk_data,
             *p = *u; *p = *v; where p might be v, then USE_STMT
             acts as a use as well as definition, so store in STMT
             is not dead.  */
-         if (gimple_loaded_syms (use_stmt)
-             && bitmap_intersect_p (gimple_loaded_syms (use_stmt),
-                                    gimple_stored_syms (use_stmt)))
-           {
-              record_voperand_set (dse_gd->stores, &bd->stores, 
-                                  gimple_uid (stmt));
-             return;
-           }
+         if (stmt != use_stmt
+             && !is_gimple_reg (gimple_assign_rhs1 (use_stmt))
+             && !is_gimple_min_invariant (gimple_assign_rhs1 (use_stmt))
+             /* ???  Should {} be invariant?  */
+             && gimple_assign_rhs_code (use_stmt) != CONSTRUCTOR
+             && refs_may_alias_p (gimple_assign_lhs (use_stmt),
+                                  gimple_assign_rhs1 (use_stmt)))
+           return;
 
          if (dump_file && (dump_flags & TDF_DETAILS))
             {
@@ -479,21 +336,7 @@ dse_optimize_stmt (struct dom_walk_data *walk_data,
             }
 
          /* Then we need to fix the operand of the consuming stmt.  */
-         stmt_lhs = USE_FROM_PTR (first_use_p);
-         FOR_EACH_SSA_VDEF_OPERAND (var1, vv, stmt, op_iter)
-           {
-             tree usevar;
-             gimple temp;
-
-             single_imm_use (DEF_FROM_PTR (var1), &use_p, &temp);
-             gcc_assert (VUSE_VECT_NUM_ELEM (*vv) == 1);
-             usevar = VUSE_ELEMENT_VAR (*vv, 0);
-             SET_USE (use_p, usevar);
-
-             /* Make sure we propagate the ABNORMAL bit setting.  */
-             if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (stmt_lhs))
-               SSA_NAME_OCCURS_IN_ABNORMAL_PHI (usevar) = 1;
-           }
+         unlink_stmt_vdef (stmt);
 
          /* Remove the dead store.  */
          gsi_remove (&gsi, true);
@@ -502,8 +345,6 @@ dse_optimize_stmt (struct dom_walk_data *walk_data,
             SSA_NAME manager.  */
          release_defs (stmt);
        }
-
-      record_voperand_set (dse_gd->stores, &bd->stores, gimple_uid (stmt));
     }
 }
 
@@ -564,6 +405,7 @@ tree_ssa_dse (void)
      this pass could be seen as an extension of DCE which needs post
      dominators.  */
   calculate_dominance_info (CDI_POST_DOMINATORS);
+  calculate_dominance_info (CDI_DOMINATORS);
 
   /* Dead store elimination is fundamentally a walk of the post-dominator
      tree and a backwards walk of statements within each block.  */
@@ -630,153 +472,3 @@ struct gimple_opt_pass pass_dse =
  }
 };
 
-/* A very simple dead store pass eliminating write only local variables.
-   The pass does not require alias information and thus can be run before
-   inlining to quickly eliminate artifacts of some common C++ constructs.  */
-
-static unsigned int
-execute_simple_dse (void)
-{
-  gimple_stmt_iterator gsi;
-  basic_block bb;
-  bitmap variables_loaded = BITMAP_ALLOC (NULL);
-  unsigned int todo = 0;
-
-  /* Collect into VARIABLES LOADED all variables that are read in function
-     body.  */
-  FOR_EACH_BB (bb)
-    for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
-
-      if (gimple_loaded_syms (gsi_stmt (gsi)))
-       bitmap_ior_into (variables_loaded,
-                        gimple_loaded_syms (gsi_stmt (gsi)));
-
-  /* Look for statements writing into the write only variables.
-     And try to remove them.  */
-
-  FOR_EACH_BB (bb)
-    for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
-      {
-       gimple stmt = gsi_stmt (gsi);
-        tree op;
-       bool removed = false;
-        ssa_op_iter iter;
-       tree size;
-
-       if (is_gimple_assign (stmt)
-           && AGGREGATE_TYPE_P (TREE_TYPE (gimple_assign_lhs (stmt)))
-           && (size = lang_hooks.expr_size (gimple_assign_lhs (stmt)))
-           && integer_zerop (size))
-         {
-           if (dump_file && (dump_flags & TDF_DETAILS))
-             {
-               fprintf (dump_file, "  Deleted zero-sized store '");
-               print_gimple_stmt (dump_file, stmt, 0, dump_flags);
-               fprintf (dump_file, "'\n");
-             }
-           removed = true;
-           gsi_remove (&gsi, true);
-           todo |= TODO_cleanup_cfg;
-         }
-       else if (gimple_stored_syms (stmt)
-                && !bitmap_empty_p (gimple_stored_syms (stmt))
-                && (is_gimple_assign (stmt)
-                    || (is_gimple_call (stmt)
-                        && gimple_call_lhs (stmt)))
-                && !bitmap_intersect_p (gimple_stored_syms (stmt),
-                                        variables_loaded))
-         {
-           unsigned int i;
-           bitmap_iterator bi;
-           bool dead = true;
-
-           /* See if STMT only stores to write-only variables and
-              verify that there are no volatile operands.  tree-ssa-operands
-              sets has_volatile_ops flag for all statements involving
-              reads and writes when aliases are not built to prevent passes
-              from removing them as dead.  The flag thus has no use for us
-              and we need to look into all operands.  */
-             
-           EXECUTE_IF_SET_IN_BITMAP (gimple_stored_syms (stmt), 0, i, bi)
-             {
-               tree var = referenced_var_lookup (i);
-               if (TREE_ADDRESSABLE (var)
-                   || is_global_var (var)
-                   || TREE_THIS_VOLATILE (var))
-                 dead = false;
-             }
-
-           if (dead && gimple_loaded_syms (stmt))
-             EXECUTE_IF_SET_IN_BITMAP (gimple_loaded_syms (stmt), 0, i, bi)
-               if (TREE_THIS_VOLATILE (referenced_var_lookup (i)))
-                 dead = false;
-
-           if (dead)
-             FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_ALL_OPERANDS)
-               if (TREE_THIS_VOLATILE (op))
-                 dead = false;
-
-           /* Look for possible occurrence var = indirect_ref (...) where
-              indirect_ref itself is volatile.  */
-
-           if (dead && is_gimple_assign (stmt)
-               && TREE_THIS_VOLATILE (gimple_assign_rhs1 (stmt)))
-             dead = false;
-
-           if (dead)
-             {
-               /* When LHS of var = call (); is dead, simplify it into
-                  call (); saving one operand.  */
-                if (is_gimple_call (stmt)
-                    && gimple_has_side_effects (stmt))
-                 {
-                   if (dump_file && (dump_flags & TDF_DETAILS))
-                     {
-                       fprintf (dump_file, "Deleted LHS of call: ");
-                       print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
-                       fprintf (dump_file, "\n");
-                     }
-                   push_stmt_changes (gsi_stmt_ptr (&gsi));
-                    gimple_call_set_lhs (stmt, NULL);
-                   pop_stmt_changes (gsi_stmt_ptr (&gsi));
-                 }
-               else
-                 {
-                   if (dump_file && (dump_flags & TDF_DETAILS))
-                     {
-                       fprintf (dump_file, "  Deleted dead store '");
-                       print_gimple_stmt (dump_file, stmt, 0, dump_flags);
-                       fprintf (dump_file, "'\n");
-                     }
-                   removed = true;
-                   gsi_remove (&gsi, true);
-                   todo |= TODO_cleanup_cfg;
-                 }
-               todo |= TODO_remove_unused_locals | TODO_ggc_collect;
-             }
-         }
-       if (!removed)
-         gsi_next (&gsi);
-      }
-  BITMAP_FREE (variables_loaded);
-  return todo;
-}
-
-struct gimple_opt_pass pass_simple_dse =
-{
- {
-  GIMPLE_PASS,
-  "sdse",                              /* name */
-  NULL,                                        /* gate */
-  execute_simple_dse,                  /* execute */
-  NULL,                                        /* sub */
-  NULL,                                        /* next */
-  0,                                   /* static_pass_number */
-  0,                                   /* tv_id */
-  PROP_ssa,                            /* properties_required */
-  0,                                   /* properties_provided */
-  0,                                   /* properties_destroyed */
-  0,                                   /* todo_flags_start */
-  TODO_dump_func                       /* todo_flags_finish */
- }
-};
index 044f843..c3e7d43 100644 (file)
@@ -594,8 +594,6 @@ tidy_after_forward_propagate_addr (gimple stmt)
 
   if (TREE_CODE (gimple_assign_rhs1 (stmt)) == ADDR_EXPR)
      recompute_tree_invariant_for_addr_expr (gimple_assign_rhs1 (stmt));
-
-  mark_symbols_for_renaming (stmt);
 }
 
 /* DEF_RHS contains the address of the 0th element in an array.
@@ -930,18 +928,24 @@ forward_propagate_addr_expr (tree name, tree rhs)
          continue;
        }
 
-      push_stmt_changes (&use_stmt);
-
       {
        gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt);
+       push_stmt_changes (&use_stmt);
        result = forward_propagate_addr_expr_1 (name, rhs, &gsi,
                                                single_use_p);
-       use_stmt = gsi_stmt (gsi);
+       /* If the use has moved to a different statement adjust
+          the update machinery.  */
+       if (use_stmt != gsi_stmt (gsi))
+         {
+           pop_stmt_changes (&use_stmt);
+           use_stmt = gsi_stmt (gsi);
+           update_stmt (use_stmt);
+         }
+       else
+         pop_stmt_changes (&use_stmt);
       }
       all &= result;
 
-      pop_stmt_changes (&use_stmt);
-
       /* Remove intermediate now unused copy and conversion chains.  */
       use_rhs = gimple_assign_rhs1 (use_stmt);
       if (result
index 0804856..e6dc78a 100644 (file)
@@ -108,7 +108,7 @@ bb_no_side_effects_p (basic_block bb)
       gimple stmt = gsi_stmt (gsi);
 
       if (gimple_has_volatile_ops (stmt)
-         || !ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
+         || gimple_vuse (stmt))
        return false;
     }
 
index 5731964..fa24745 100644 (file)
@@ -797,11 +797,9 @@ remove_unused_locals (void)
      pass is performed.  */
   FOR_EACH_REFERENCED_VAR (t, rvi)
     if (!is_global_var (t)
-       && !MTAG_P (t)
        && TREE_CODE (t) != PARM_DECL
        && TREE_CODE (t) != RESULT_DECL
        && !(ann = var_ann (t))->used
-       && !ann->symbol_mem_tag
        && !TREE_ADDRESSABLE (t)
        && (optimize || DECL_ARTIFICIAL (t)))
       remove_referenced_var (t);
index fe7a222..c9d2358 100644 (file)
@@ -362,7 +362,7 @@ movement_possibility (gimple stmt)
   if (gimple_get_lhs (stmt) == NULL_TREE)
     return MOVE_IMPOSSIBLE;
 
-  if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_DEFS))
+  if (gimple_vdef (stmt))
     return MOVE_IMPOSSIBLE;
 
   if (stmt_ends_bb_p (stmt)
@@ -681,7 +681,7 @@ determine_max_movement (gimple stmt, bool must_preserve_exec)
     if (!add_dependency (val, lim_data, loop, true))
       return false;
 
-  if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_USES))
+  if (gimple_vuse (stmt))
     {
       mem_ref_p ref = mem_ref_in_stmt (stmt);
 
@@ -694,7 +694,7 @@ determine_max_movement (gimple stmt, bool must_preserve_exec)
        }
       else
        {
-         FOR_EACH_SSA_TREE_OPERAND (val, stmt, iter, SSA_OP_VIRTUAL_USES)
+         if ((val = gimple_vuse (stmt)) != NULL_TREE)
            {
              if (!add_dependency (val, lim_data, loop, false))
                return false;
@@ -1080,7 +1080,7 @@ move_computations (void)
   fini_walk_dominator_tree (&walk_data);
 
   gsi_commit_edge_inserts ();
-  if (need_ssa_update_p ())
+  if (need_ssa_update_p (cfun))
     rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
 }
 
@@ -1309,13 +1309,12 @@ gather_mem_refs_stmt (struct loop *loop, gimple stmt)
   hashval_t hash;
   PTR *slot;
   mem_ref_p ref;
-  ssa_op_iter oi;
   tree vname;
   bool is_stored;
   bitmap clvops;
   unsigned id;
 
-  if (ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
+  if (!gimple_vuse (stmt))
     return;
 
   mem = simple_mem_ref_in_stmt (stmt, &is_stored);
@@ -1347,14 +1346,14 @@ gather_mem_refs_stmt (struct loop *loop, gimple stmt)
   if (is_stored)
     mark_ref_stored (ref, loop);
 
-  FOR_EACH_SSA_TREE_OPERAND (vname, stmt, oi, SSA_OP_VIRTUAL_USES)
+  if ((vname = gimple_vuse (stmt)) != NULL_TREE)
     bitmap_set_bit (ref->vops, DECL_UID (SSA_NAME_VAR (vname)));
   record_mem_ref_loc (ref, loop, stmt, mem);
   return;
 
 fail:
   clvops = VEC_index (bitmap, memory_accesses.clobbered_vops, loop->num);
-  FOR_EACH_SSA_TREE_OPERAND (vname, stmt, oi, SSA_OP_VIRTUAL_USES)
+  if ((vname = gimple_vuse (stmt)) != NULL_TREE)
     bitmap_set_bit (clvops, DECL_UID (SSA_NAME_VAR (vname)));
 }
 
index e278c55..5c2f6af 100644 (file)
@@ -442,7 +442,7 @@ empty_loop_p (struct loop *loop)
        {
          gimple stmt = gsi_stmt (gsi);
 
-         if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_DEFS)
+         if (gimple_vdef (stmt)
              || gimple_has_volatile_ops (stmt))
            {
              free (body);
index fcaf784..37865e2 100644 (file)
@@ -5222,63 +5222,6 @@ unshare_and_remove_ssa_names (tree ref)
   return ref;
 }
 
-/* Extract the alias analysis info for the memory reference REF.  There are
-   several ways how this information may be stored and what precisely is
-   its semantics depending on the type of the reference, but there always is
-   somewhere hidden one _DECL node that is used to determine the set of
-   virtual operands for the reference.  The code below deciphers this jungle
-   and extracts this single useful piece of information.  */
-
-static tree
-get_ref_tag (tree ref, tree orig)
-{
-  tree var = get_base_address (ref);
-  tree aref = NULL_TREE, tag, sv;
-  HOST_WIDE_INT offset, size, maxsize;
-
-  for (sv = orig; handled_component_p (sv); sv = TREE_OPERAND (sv, 0))
-    {
-      aref = get_ref_base_and_extent (sv, &offset, &size, &maxsize);
-      if (ref)
-       break;
-    }
-
-  if (!var)
-    return NULL_TREE;
-
-  if (TREE_CODE (var) == INDIRECT_REF)
-    {
-      /* If the base is a dereference of a pointer, first check its name memory
-        tag.  If it does not have one, use its symbol memory tag.  */
-      var = TREE_OPERAND (var, 0);
-      if (TREE_CODE (var) != SSA_NAME)
-       return NULL_TREE;
-
-      if (SSA_NAME_PTR_INFO (var))
-       {
-         tag = SSA_NAME_PTR_INFO (var)->name_mem_tag;
-         if (tag)
-           return tag;
-       }
-      var = SSA_NAME_VAR (var);
-      tag = symbol_mem_tag (var);
-      gcc_assert (tag != NULL_TREE);
-      return tag;
-    }
-  else
-    { 
-      if (!DECL_P (var))
-       return NULL_TREE;
-
-      tag = symbol_mem_tag (var);
-      if (tag)
-       return tag;
-
-      return var;
-    }
-}
-
 /* Copies the reference information from OLD_REF to NEW_REF.  */
 
 static void
@@ -5287,10 +5230,7 @@ copy_ref_info (tree new_ref, tree old_ref)
   if (TREE_CODE (old_ref) == TARGET_MEM_REF)
     copy_mem_ref_info (new_ref, old_ref);
   else
-    {
-      TMR_ORIGINAL (new_ref) = unshare_and_remove_ssa_names (old_ref);
-      TMR_TAG (new_ref) = get_ref_tag (old_ref, TMR_ORIGINAL (new_ref));
-    }
+    TMR_ORIGINAL (new_ref) = unshare_and_remove_ssa_names (old_ref);
 }
 
 /* Rewrites USE (address that is an iv) using candidate CAND.  */
index d657e1a..6547382 100644 (file)
@@ -1993,17 +1993,13 @@ chain_of_csts_start (struct loop *loop, tree x)
 
   code = gimple_assign_rhs_code (stmt);
   if (gimple_references_memory_p (stmt)
-      /* Before alias information is computed, operand scanning marks
-        statements that write memory volatile.  However, the statements
-        that only read memory are not marked, thus gimple_references_memory_p
-        returns false for them.  */
       || TREE_CODE_CLASS (code) == tcc_reference
-      || TREE_CODE_CLASS (code) == tcc_declaration
-      || SINGLE_SSA_DEF_OPERAND (stmt, SSA_OP_DEF) == NULL_DEF_OPERAND_P)
+      || (code == ADDR_EXPR
+         && !is_gimple_min_invariant (gimple_assign_rhs1 (stmt))))
     return NULL;
 
   use = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_USE);
-  if (use == NULL_USE_OPERAND_P)
+  if (use == NULL_TREE)
     return NULL;
 
   return chain_of_csts_start (loop, use);
index d0e460c..bcff26a 100644 (file)
@@ -502,7 +502,7 @@ gather_memory_references (struct loop *loop, bool *no_other_refs)
 
          if (gimple_code (stmt) != GIMPLE_ASSIGN)
            {
-             if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS)
+             if (gimple_vuse (stmt)
                  || (is_gimple_call (stmt)
                      && !(gimple_call_flags (stmt) & ECF_CONST)))
                *no_other_refs = false;
index 85a0a08..56d8e84 100644 (file)
@@ -75,11 +75,6 @@ along with GCC; see the file COPYING3.  If not see
    operand vector for VUSE, then the new vector will also be modified
    such that it contains 'a_5' rather than 'a'.  */
 
-/* Helper functions from gimple.c.  These are GIMPLE manipulation
-   routines that only the operand scanner should need.  */
-void gimple_set_stored_syms (gimple, bitmap, bitmap_obstack *);
-void gimple_set_loaded_syms (gimple, bitmap, bitmap_obstack *);
-
 /* Structure storing statistics on how many call clobbers we have, and
    how many where avoided.  */
 
@@ -137,69 +132,26 @@ static VEC(tree,heap) *build_defs;
 /* Array for building all the use operands.  */
 static VEC(tree,heap) *build_uses;
 
-/* Set for building all the VDEF operands.  */
-static VEC(tree,heap) *build_vdefs;
+/* The built VDEF operand.  */
+static tree build_vdef;
 
-/* Set for building all the VUSE operands.  */
-static VEC(tree,heap) *build_vuses;
+/* The built VUSE operand.  */
+static tree build_vuse;
 
 /* Bitmap obstack for our datastructures that needs to survive across  
    compilations of multiple functions.  */
 static bitmap_obstack operands_bitmap_obstack;
 
-/* Set for building all the loaded symbols.  */
-static bitmap build_loads;
-
-/* Set for building all the stored symbols.  */
-static bitmap build_stores;
-
 static void get_expr_operands (gimple, tree *, int);
 
 /* Number of functions with initialized ssa_operands.  */
 static int n_initialized = 0;
 
-/* Statement change buffer.  Data structure used to record state
-   information for statements.  This is used to determine what needs
-   to be done in order to update the SSA web after a statement is
-   modified by a pass.  If STMT is a statement that has just been
-   created, or needs to be folded via fold_stmt, or anything that
-   changes its physical structure then the pass should:
-
-   1- Call push_stmt_changes (&stmt) to record the current state of
-      STMT before any modifications are made.
-
-   2- Make all appropriate modifications to the statement.
-
-   3- Call pop_stmt_changes (&stmt) to find new symbols that
-      need to be put in SSA form, SSA name mappings for names that
-      have disappeared, recompute invariantness for address
-      expressions, cleanup EH information, etc.
-
-   If it is possible to determine that the statement was not modified,
-   instead of calling pop_stmt_changes it is quicker to call
-   discard_stmt_changes to avoid the expensive and unnecessary operand
-   re-scan and change comparison.  */
-
-struct scb_d
-{
-  /* Pointer to the statement being modified.  */
-  gimple *stmt_p;
-
-  /* If the statement references memory these are the sets of symbols
-     loaded and stored by the statement.  */
-  bitmap loads;
-  bitmap stores;
-};
-
-typedef struct scb_d *scb_t;
-DEF_VEC_P(scb_t);
-DEF_VEC_ALLOC_P(scb_t,heap);
-
-/* Stack of statement change buffers (SCB).  Every call to
-   push_stmt_changes pushes a new buffer onto the stack.  Calls to
-   pop_stmt_changes pop a buffer off of the stack and compute the set
+/* Stack of statements to change.  Every call to
+   push_stmt_changes pushes the stmt onto the stack.  Calls to
+   pop_stmt_changes pop a stmt off of the stack and compute the set
    of changes for the popped statement.  */
-static VEC(scb_t,heap) *scb_stack;
+static VEC(gimple_p,heap) *scb_stack;
 
 /* Return the DECL_UID of the base variable of T.  */
 
@@ -213,54 +165,6 @@ get_name_decl (const_tree t)
 }
 
 
-/* Comparison function for qsort used in operand_build_sort_virtual.  */
-
-int
-operand_build_cmp (const void *p, const void *q)
-{
-  const_tree const e1 = *((const_tree const *)p);
-  const_tree const e2 = *((const_tree const *)q);
-  const unsigned int u1 = get_name_decl (e1);
-  const unsigned int u2 = get_name_decl (e2);
-
-  /* We want to sort in ascending order.  They can never be equal.  */
-#ifdef ENABLE_CHECKING
-  gcc_assert (u1 != u2);
-#endif
-  return (u1 > u2 ? 1 : -1);
-}
-
-
-/* Sort the virtual operands in LIST from lowest DECL_UID to highest.  */
-
-static inline void
-operand_build_sort_virtual (VEC(tree,heap) *list)
-{
-  int num = VEC_length (tree, list);
-
-  if (num < 2)
-    return;
-
-  if (num == 2)
-    {
-      if (get_name_decl (VEC_index (tree, list, 0)) 
-         > get_name_decl (VEC_index (tree, list, 1)))
-       {  
-         /* Swap elements if in the wrong order.  */
-         tree tmp = VEC_index (tree, list, 0);
-         VEC_replace (tree, list, 0, VEC_index (tree, list, 1));
-         VEC_replace (tree, list, 1, tmp);
-       }
-      return;
-    }
-
-  /* There are 3 or more elements, call qsort.  */
-  qsort (VEC_address (tree, list), 
-        VEC_length (tree, list), 
-        sizeof (tree),
-        operand_build_cmp);
-}
-
 /*  Return true if the SSA operands cache is active.  */
 
 bool
@@ -276,94 +180,44 @@ ssa_operands_active (void)
   return cfun->gimple_df && gimple_ssa_operands (cfun)->ops_active;
 }
 
+/* Create the VOP variable, an artificial global variable to act as a
+   representative of all of the virtual operands FUD chain.  */
 
-/* VOPs are of variable sized, so the free list maps "free buckets" to the 
-   following table:  
-    bucket   # operands
-    ------   ----------
-       0       1
-       1       2
-         ...
-       15      16
-       16      17-24
-       17      25-32
-       18      31-40
-         ...
-       29      121-128
-   Any VOPs larger than this are simply added to the largest bucket when they
-   are freed.  */
-
-
-/* Return the number of operands used in bucket BUCKET.  */
-
-static inline int
-vop_free_bucket_size (int bucket)
-{
-#ifdef ENABLE_CHECKING
-  gcc_assert (bucket >= 0 && bucket < NUM_VOP_FREE_BUCKETS);
-#endif
-  if (bucket < 16)
-    return bucket + 1;
-  return (bucket - 13) * 8;
-}
-
-
-/* For a vop of NUM operands, return the bucket NUM belongs to.  If NUM is 
-   beyond the end of the bucket table, return -1.  */
-
-static inline int 
-vop_free_bucket_index (int num)
-{
-  gcc_assert (num > 0 && NUM_VOP_FREE_BUCKETS > 16);
-
-  /* Sizes 1 through 16 use buckets 0-15.  */
-  if (num <= 16)
-    return num - 1;
-  /* Buckets 16 - NUM_VOP_FREE_BUCKETS represent 8 unit chunks.  */
-  num = 14 + (num - 1) / 8;
-  if (num >= NUM_VOP_FREE_BUCKETS)
-    return -1;
-  else
-    return num;
-}
-
-
-/* Initialize the VOP free buckets.  */
-
-static inline void
-init_vop_buckets (void)
-{
-  int x;
-
-  for (x = 0; x < NUM_VOP_FREE_BUCKETS; x++)
-    gimple_ssa_operands (cfun)->vop_free_buckets[x] = NULL;
-}
-
-
-/* Add PTR to the appropriate VOP bucket.  */
-
-static inline void
-add_vop_to_freelist (voptype_p ptr)
+static void
+create_vop_var (void)
 {
-  int bucket = vop_free_bucket_index (VUSE_VECT_NUM_ELEM (ptr->usev));
-
-  /* Too large, use the largest bucket so its not a complete throw away.  */
-  if (bucket == -1)
-    bucket = NUM_VOP_FREE_BUCKETS - 1;
-
-  ptr->next = gimple_ssa_operands (cfun)->vop_free_buckets[bucket];
-  gimple_ssa_operands (cfun)->vop_free_buckets[bucket] = ptr;
+  tree global_var;
+
+  gcc_assert (cfun->gimple_df->vop == NULL_TREE);
+
+  global_var = build_decl (VAR_DECL, get_identifier (".MEM"),
+                          void_type_node);
+  DECL_ARTIFICIAL (global_var) = 1;
+  TREE_READONLY (global_var) = 0;
+  DECL_EXTERNAL (global_var) = 1;
+  TREE_STATIC (global_var) = 1;
+  TREE_USED (global_var) = 1;
+  DECL_CONTEXT (global_var) = NULL_TREE;
+  TREE_THIS_VOLATILE (global_var) = 0;
+  TREE_ADDRESSABLE (global_var) = 0;
+
+  create_var_ann (global_var);
+  add_referenced_var (global_var);
+  cfun->gimple_df->vop = global_var;
 }
 
-/* These are the sizes of the operand memory  buffer which gets allocated each 
-   time more operands space is required.  The final value is the amount that is
-   allocated every time after that.  */
+/* These are the sizes of the operand memory buffer in bytes which gets
+   allocated each time more operands space is required.  The final value is
+   the amount that is allocated every time after that.
+   In 1k we can fit 25 use operands (or 63 def operands) on a host with
+   8 byte pointers, that would be 10 statements each with 1 def and 2
+   uses.  */
   
 #define OP_SIZE_INIT   0
-#define OP_SIZE_1      30
-#define OP_SIZE_2      110
-#define OP_SIZE_3      511
+#define OP_SIZE_1      (1024 - sizeof (void *))
+#define OP_SIZE_2      (1024 * 4 - sizeof (void *))
+#define OP_SIZE_3      (1024 * 16 - sizeof (void *))
 
 /* Initialize the operand cache routines.  */
 
@@ -374,22 +228,19 @@ init_ssa_operands (void)
     {
       build_defs = VEC_alloc (tree, heap, 5);
       build_uses = VEC_alloc (tree, heap, 10);
-      build_vuses = VEC_alloc (tree, heap, 25);
-      build_vdefs = VEC_alloc (tree, heap, 25);
+      build_vuse = NULL_TREE;
+      build_vdef = NULL_TREE;
       bitmap_obstack_initialize (&operands_bitmap_obstack);
-      build_loads = BITMAP_ALLOC (&operands_bitmap_obstack);
-      build_stores = BITMAP_ALLOC (&operands_bitmap_obstack);
-      scb_stack = VEC_alloc (scb_t, heap, 20);
+      scb_stack = VEC_alloc (gimple_p, heap, 20);
     }
 
   gcc_assert (gimple_ssa_operands (cfun)->operand_memory == NULL);
-  gcc_assert (gimple_ssa_operands (cfun)->mpt_table == NULL);
   gimple_ssa_operands (cfun)->operand_memory_index
      = gimple_ssa_operands (cfun)->ssa_operand_mem_size;
   gimple_ssa_operands (cfun)->ops_active = true;
   memset (&clobber_stats, 0, sizeof (clobber_stats));
-  init_vop_buckets ();
   gimple_ssa_operands (cfun)->ssa_operand_mem_size = OP_SIZE_INIT;
+  create_vop_var ();
 }
 
 
@@ -399,21 +250,17 @@ void
 fini_ssa_operands (void)
 {
   struct ssa_operand_memory_d *ptr;
-  unsigned ix;
-  tree mpt;
 
   if (!--n_initialized)
     {
       VEC_free (tree, heap, build_defs);
       VEC_free (tree, heap, build_uses);
-      VEC_free (tree, heap, build_vdefs);
-      VEC_free (tree, heap, build_vuses);
-      BITMAP_FREE (build_loads);
-      BITMAP_FREE (build_stores);
+      build_vdef = NULL_TREE;
+      build_vuse = NULL_TREE;
 
       /* The change buffer stack had better be empty.  */
-      gcc_assert (VEC_length (scb_t, scb_stack) == 0);
-      VEC_free (scb_t, heap, scb_stack);
+      gcc_assert (VEC_length (gimple_p, scb_stack) == 0);
+      VEC_free (gimple_p, heap, scb_stack);
       scb_stack = NULL;
     }
 
@@ -427,21 +274,13 @@ fini_ssa_operands (void)
       ggc_free (ptr);
     }
 
-  for (ix = 0;
-       VEC_iterate (tree, gimple_ssa_operands (cfun)->mpt_table, ix, mpt);
-       ix++)
-    {
-      if (mpt)
-       BITMAP_FREE (MPT_SYMBOLS (mpt));
-    }
-
-  VEC_free (tree, heap, gimple_ssa_operands (cfun)->mpt_table);
-
   gimple_ssa_operands (cfun)->ops_active = false;
 
   if (!n_initialized)
     bitmap_obstack_release (&operands_bitmap_obstack);
 
+  cfun->gimple_df->vop = NULL_TREE;
+
   if (dump_file && (dump_flags & TDF_STATS))
     {
       fprintf (dump_file, "Original clobbered vars:           %d\n",
@@ -460,47 +299,45 @@ fini_ssa_operands (void)
 }
 
 
-/* Return memory for operands of SIZE chunks.  */
+/* Return memory for an operand of size SIZE.  */
                                                                               
 static inline void *
 ssa_operand_alloc (unsigned size)
 {
   char *ptr;
 
+  gcc_assert (size == sizeof (struct use_optype_d)
+             || size == sizeof (struct def_optype_d));
+
   if (gimple_ssa_operands (cfun)->operand_memory_index + size
       >= gimple_ssa_operands (cfun)->ssa_operand_mem_size)
     {
       struct ssa_operand_memory_d *ptr;
 
-      if (gimple_ssa_operands (cfun)->ssa_operand_mem_size == OP_SIZE_INIT)
-       gimple_ssa_operands (cfun)->ssa_operand_mem_size
-          = OP_SIZE_1 * sizeof (struct voptype_d);
-      else
-       if (gimple_ssa_operands (cfun)->ssa_operand_mem_size
-           == OP_SIZE_1 * sizeof (struct voptype_d))
-         gimple_ssa_operands (cfun)->ssa_operand_mem_size
-            = OP_SIZE_2 * sizeof (struct voptype_d);
-       else
-         gimple_ssa_operands (cfun)->ssa_operand_mem_size
-            = OP_SIZE_3 * sizeof (struct voptype_d);
-
-      /* Go right to the maximum size if the request is too large.  */
-      if (size > gimple_ssa_operands (cfun)->ssa_operand_mem_size)
-        gimple_ssa_operands (cfun)->ssa_operand_mem_size
-         = OP_SIZE_3 * sizeof (struct voptype_d);
-
-      /* We can reliably trigger the case that we need arbitrary many
-        operands (see PR34093), so allocate a buffer just for this request.  */
-      if (size > gimple_ssa_operands (cfun)->ssa_operand_mem_size)
-       gimple_ssa_operands (cfun)->ssa_operand_mem_size = size;
+      switch (gimple_ssa_operands (cfun)->ssa_operand_mem_size)
+       {
+       case OP_SIZE_INIT:
+         gimple_ssa_operands (cfun)->ssa_operand_mem_size = OP_SIZE_1;
+         break;
+       case OP_SIZE_1:
+         gimple_ssa_operands (cfun)->ssa_operand_mem_size = OP_SIZE_2;
+         break;
+       case OP_SIZE_2:
+       case OP_SIZE_3:
+         gimple_ssa_operands (cfun)->ssa_operand_mem_size = OP_SIZE_3;
+         break;
+       default:
+         gcc_unreachable ();
+       }
 
       ptr = (struct ssa_operand_memory_d *) 
-             ggc_alloc (sizeof (struct ssa_operand_memory_d) 
-                        + gimple_ssa_operands (cfun)->ssa_operand_mem_size - 1);
+             ggc_alloc (sizeof (void *)
+                        + gimple_ssa_operands (cfun)->ssa_operand_mem_size);
       ptr->next = gimple_ssa_operands (cfun)->operand_memory;
       gimple_ssa_operands (cfun)->operand_memory = ptr;
       gimple_ssa_operands (cfun)->operand_memory_index = 0;
     }
+
   ptr = &(gimple_ssa_operands (cfun)->operand_memory
          ->mem[gimple_ssa_operands (cfun)->operand_memory_index]);
   gimple_ssa_operands (cfun)->operand_memory_index += size;
@@ -546,55 +383,6 @@ alloc_use (void)
 }
 
 
-/* Allocate a vop with NUM elements.  */
-
-static inline struct voptype_d *
-alloc_vop (int num)
-{
-  struct voptype_d *ret = NULL;
-  int alloc_size = 0;
-
-  int bucket = vop_free_bucket_index (num);
-  if (bucket != -1)
-    {
-      /* If there is a free operand, use it.  */
-      if (gimple_ssa_operands (cfun)->vop_free_buckets[bucket] != NULL)
-       {
-         ret = gimple_ssa_operands (cfun)->vop_free_buckets[bucket];
-         gimple_ssa_operands (cfun)->vop_free_buckets[bucket] = 
-                 gimple_ssa_operands (cfun)->vop_free_buckets[bucket]->next;
-       }
-      else
-        alloc_size = vop_free_bucket_size(bucket);
-    }
-  else
-    alloc_size = num;
-
-  if (alloc_size > 0)
-    ret = (struct voptype_d *)ssa_operand_alloc (
-       sizeof (struct voptype_d) + (alloc_size - 1) * sizeof (vuse_element_t));
-
-  VUSE_VECT_NUM_ELEM (ret->usev) = num;
-  return ret;
-}
-
-
-/* This routine makes sure that PTR is in an immediate use list, and makes
-   sure the stmt pointer is set to the current stmt.  */
-
-static inline void
-set_virtual_use_link (use_operand_p ptr, gimple stmt)
-{
-  /*  fold_stmt may have changed the stmt pointers.  */
-  if (ptr->loc.stmt != stmt)
-    ptr->loc.stmt = stmt;
-
-  /* If this use isn't in a list, add it to the correct list.  */
-  if (!ptr->prev)
-    link_imm_use (ptr, *(ptr->use));
-}
-
-
 /* Adds OP to the list of defs after LAST.  */
 
 static inline def_optype_p 
@@ -626,56 +414,6 @@ add_use_op (gimple stmt, tree *op, use_optype_p last)
 }
 
 
-/* Return a virtual op pointer with NUM elements which are all
-   initialized to OP and are linked into the immediate uses for STMT.
-   The new vop is appended after PREV.  */
-
-static inline voptype_p
-add_vop (gimple stmt, tree op, int num, voptype_p prev)
-{
-  voptype_p new_vop;
-  int x;
-
-  new_vop = alloc_vop (num);
-  for (x = 0; x < num; x++)
-    {
-      VUSE_OP_PTR (new_vop, x)->prev = NULL;
-      SET_VUSE_OP (new_vop, x, op);
-      VUSE_OP_PTR (new_vop, x)->use = &new_vop->usev.uses[x].use_var;
-      link_imm_use_stmt (VUSE_OP_PTR (new_vop, x),
-                        new_vop->usev.uses[x].use_var, stmt);
-    }
-
-  if (prev)
-    prev->next = new_vop;
-  new_vop->next = NULL;
-  return new_vop;
-}
-
-
-/* Adds OP to the list of vuses of statement STMT after LAST, and moves
-   LAST to the new element.  */
-
-static inline voptype_p
-add_vuse_op (gimple stmt, tree op, int num, voptype_p last)
-{
-  voptype_p new_vop = add_vop (stmt, op, num, last);
-  VDEF_RESULT (new_vop) = NULL_TREE;
-  return new_vop;
-}
-
-
-/* Adds OP to the list of vdefs of statement STMT after LAST, and moves
-   LAST to the new element.  */
-
-static inline voptype_p
-add_vdef_op (gimple stmt, tree op, int num, voptype_p last)
-{
-  voptype_p new_vop = add_vop (stmt, op, num, last);
-  VDEF_RESULT (new_vop) = op;
-  return new_vop;
-}
-  
 
 /* Takes elements from build_defs and turns them into def operands of STMT.
    TODO -- Make build_defs VEC of tree *.  */
@@ -691,6 +429,19 @@ finalize_ssa_defs (gimple stmt)
   /* There should only be a single real definition per assignment.  */
   gcc_assert ((stmt && gimple_code (stmt) != GIMPLE_ASSIGN) || num <= 1);
 
+  /* Pre-pend the vdef we may have built.  */
+  if (build_vdef != NULL_TREE)
+    {
+      tree oldvdef = gimple_vdef (stmt);
+      if (oldvdef
+         && TREE_CODE (oldvdef) == SSA_NAME)
+       oldvdef = SSA_NAME_VAR (oldvdef);
+      if (oldvdef != build_vdef)
+       gimple_set_vdef (stmt, build_vdef);
+      VEC_safe_insert (tree, heap, build_defs, 0, (tree)gimple_vdef_ptr (stmt));
+      ++num;
+    }
+
   new_list.next = NULL;
   last = &new_list;
 
@@ -698,6 +449,23 @@ finalize_ssa_defs (gimple stmt)
 
   new_i = 0;
 
+  /* Clear and unlink a no longer necessary VDEF.  */
+  if (build_vdef == NULL_TREE
+      && gimple_vdef (stmt) != NULL_TREE)
+    {
+      if (TREE_CODE (gimple_vdef (stmt)) == SSA_NAME)
+       {
+         unlink_stmt_vdef (stmt);
+         release_ssa_name (gimple_vdef (stmt));
+       }
+      gimple_set_vdef (stmt, NULL_TREE);
+    }
+
+  /* If we have a non-SSA_NAME VDEF, mark it for renaming.  */
+  if (gimple_vdef (stmt)
+      && TREE_CODE (gimple_vdef (stmt)) != SSA_NAME)
+    mark_sym_for_renaming (gimple_vdef (stmt));
+
   /* Check for the common case of 1 def that hasn't changed.  */
   if (old_ops && old_ops->next == NULL && num == 1
       && (tree *) VEC_index (tree, build_defs, 0) == DEF_OP_PTR (old_ops))
@@ -716,17 +484,6 @@ finalize_ssa_defs (gimple stmt)
 
   /* Now set the stmt's operands.  */
   gimple_set_def_ops (stmt, new_list.next);
-
-#ifdef ENABLE_CHECKING
-  {
-    def_optype_p ptr;
-    unsigned x = 0;
-    for (ptr = gimple_def_ops (stmt); ptr; ptr = ptr->next)
-      x++;
-
-    gcc_assert (x == num);
-  }
-#endif
 }
 
 
@@ -740,11 +497,29 @@ finalize_ssa_uses (gimple stmt)
   struct use_optype_d new_list;
   use_optype_p old_ops, ptr, last;
 
+  /* Pre-pend the VUSE we may have built.  */
+  if (build_vuse != NULL_TREE)
+    {
+      tree oldvuse = gimple_vuse (stmt);
+      if (oldvuse
+         && TREE_CODE (oldvuse) == SSA_NAME)
+       oldvuse = SSA_NAME_VAR (oldvuse);
+      if (oldvuse != (build_vuse != NULL_TREE
+                     ? build_vuse : build_vdef))
+       gimple_set_vuse (stmt, NULL_TREE);
+      VEC_safe_insert (tree, heap, build_uses, 0, (tree)gimple_vuse_ptr (stmt));
+    }
+
   new_list.next = NULL;
   last = &new_list;
 
   old_ops = gimple_use_ops (stmt);
 
+  /* Clear a no longer necessary VUSE.  */
+  if (build_vuse == NULL_TREE
+      && gimple_vuse (stmt) != NULL_TREE)
+    gimple_set_vuse (stmt, NULL_TREE);
+
   /* If there is anything in the old list, free it.  */
   if (old_ops)
     {
@@ -754,6 +529,15 @@ finalize_ssa_uses (gimple stmt)
       gimple_ssa_operands (cfun)->free_uses = old_ops;
     }
 
+  /* If we added a VUSE, make sure to set the operand if it is not already
+     present and mark it for renaming.  */
+  if (build_vuse != NULL_TREE
+      && gimple_vuse (stmt) == NULL_TREE)
+    {
+      gimple_set_vuse (stmt, gimple_vop (cfun));
+      mark_sym_for_renaming (gimple_vop (cfun));
+    }
+
   /* Now create nodes for all the new nodes.  */
   for (new_i = 0; new_i < VEC_length (tree, build_uses); new_i++)
     last = add_use_op (stmt, 
@@ -762,259 +546,6 @@ finalize_ssa_uses (gimple stmt)
 
   /* Now set the stmt's operands.  */
   gimple_set_use_ops (stmt, new_list.next);
-
-#ifdef ENABLE_CHECKING
-  {
-    unsigned x = 0;
-    for (ptr = gimple_use_ops (stmt); ptr; ptr = ptr->next)
-      x++;
-
-    gcc_assert (x == VEC_length (tree, build_uses));
-  }
-#endif
-}
-
-
-/* Takes elements from BUILD_VDEFS and turns them into vdef operands of
-   STMT.  */
-
-static inline void
-finalize_ssa_vdefs (gimple stmt)
-{
-  unsigned new_i;
-  struct voptype_d new_list;
-  voptype_p old_ops, ptr, last;
-
-  /* Set the symbols referenced by STMT.  */
-  gimple_set_stored_syms (stmt, build_stores, &operands_bitmap_obstack);
-
-  /* If aliases have not been computed, do not instantiate a virtual
-     operator on STMT.  Initially, we only compute the SSA form on
-     GIMPLE registers.  The virtual SSA form is only computed after
-     alias analysis, so virtual operators will remain unrenamed and
-     the verifier will complain.  However, alias analysis needs to
-     access symbol load/store information, so we need to compute
-     those.  */
-  if (!gimple_aliases_computed_p (cfun))
-    return;
-
-  new_list.next = NULL;
-  last = &new_list;
-
-  old_ops = gimple_vdef_ops (stmt);
-  new_i = 0;
-  while (old_ops && new_i < VEC_length (tree, build_vdefs))
-    {
-      tree op = VEC_index (tree, build_vdefs, new_i);
-      unsigned new_uid = get_name_decl (op);
-      unsigned old_uid = get_name_decl (VDEF_RESULT (old_ops));
-
-      /* FIXME, for now each VDEF operator should have at most one
-        operand in their RHS.  */
-      gcc_assert (VDEF_NUM (old_ops) == 1);
-
-      if (old_uid == new_uid)
-        {
-         /* If the symbols are the same, reuse the existing operand.  */
-         last->next = old_ops;
-         last = old_ops;
-         old_ops = old_ops->next;
-         last->next = NULL;
-         set_virtual_use_link (VDEF_OP_PTR (last, 0), stmt);
-         new_i++;
-       }
-      else if (old_uid < new_uid)
-       {
-         /* If old is less than new, old goes to the free list.  */
-         voptype_p next;
-         delink_imm_use (VDEF_OP_PTR (old_ops, 0));
-         next = old_ops->next;
-         add_vop_to_freelist (old_ops);
-         old_ops = next;
-       }
-      else
-       {
-         /* This is a new operand.  */
-         last = add_vdef_op (stmt, op, 1, last);
-         new_i++;
-       }
-    }
-
-  /* If there is anything remaining in BUILD_VDEFS, simply emit it.  */
-  for ( ; new_i < VEC_length (tree, build_vdefs); new_i++)
-    last = add_vdef_op (stmt, VEC_index (tree, build_vdefs, new_i), 1, last);
-
-  /* If there is anything in the old list, free it.  */
-  if (old_ops)
-    {
-      for (ptr = old_ops; ptr; ptr = last)
-        {
-         last = ptr->next;
-         delink_imm_use (VDEF_OP_PTR (ptr, 0));
-         add_vop_to_freelist (ptr);
-       }
-    }
-
-  /* Now set STMT's operands.  */
-  gimple_set_vdef_ops (stmt, new_list.next);
-
-#ifdef ENABLE_CHECKING
-  {
-    unsigned x = 0;
-    for (ptr = gimple_vdef_ops (stmt); ptr; ptr = ptr->next)
-      x++;
-
-    gcc_assert (x == VEC_length (tree, build_vdefs));
-  }
-#endif
-}
-
-
-/* Takes elements from BUILD_VUSES and turns them into VUSE operands of
-   STMT.  */
-
-static inline void
-finalize_ssa_vuse_ops (gimple stmt)
-{
-  unsigned new_i, old_i;
-  voptype_p old_ops, last;
-  VEC(tree,heap) *new_ops;
-
-  /* Set the symbols referenced by STMT.  */
-  gimple_set_loaded_syms (stmt, build_loads, &operands_bitmap_obstack);
-
-  /* If aliases have not been computed, do not instantiate a virtual
-     operator on STMT.  Initially, we only compute the SSA form on
-     GIMPLE registers.  The virtual SSA form is only computed after
-     alias analysis, so virtual operators will remain unrenamed and
-     the verifier will complain.  However, alias analysis needs to
-     access symbol load/store information, so we need to compute
-     those.  */
-  if (!gimple_aliases_computed_p (cfun))
-    return;
-
-  /* STMT should have at most one VUSE operator.  */
-  old_ops = gimple_vuse_ops (stmt);
-  gcc_assert (old_ops == NULL || old_ops->next == NULL);
-
-  new_ops = NULL;
-  new_i = old_i = 0;
-  while (old_ops
-         && old_i < VUSE_NUM (old_ops)
-        && new_i < VEC_length (tree, build_vuses))
-    {
-      tree new_op = VEC_index (tree, build_vuses, new_i);
-      tree old_op = VUSE_OP (old_ops, old_i);
-      unsigned new_uid = get_name_decl (new_op);
-      unsigned old_uid = get_name_decl (old_op);
-
-      if (old_uid == new_uid)
-        {
-         /* If the symbols are the same, reuse the existing operand.  */
-         VEC_safe_push (tree, heap, new_ops, old_op);
-         new_i++;
-         old_i++;
-       }
-      else if (old_uid < new_uid)
-       {
-         /* If OLD_UID is less than NEW_UID, the old operand has
-            disappeared, skip to the next old operand.  */
-         old_i++;
-       }
-      else
-       {
-         /* This is a new operand.  */
-         VEC_safe_push (tree, heap, new_ops, new_op);
-         new_i++;
-       }
-    }
-
-  /* If there is anything remaining in the build_vuses list, simply emit it.  */
-  for ( ; new_i < VEC_length (tree, build_vuses); new_i++)
-    VEC_safe_push (tree, heap, new_ops, VEC_index (tree, build_vuses, new_i));
-
-  /* If there is anything in the old list, free it.  */
-  if (old_ops)
-    {
-      for (old_i = 0; old_i < VUSE_NUM (old_ops); old_i++)
-       delink_imm_use (VUSE_OP_PTR (old_ops, old_i));
-      add_vop_to_freelist (old_ops);
-      gimple_set_vuse_ops (stmt, NULL);
-    }
-
-  /* If there are any operands, instantiate a VUSE operator for STMT.  */
-  if (new_ops)
-    {
-      tree op;
-      unsigned i;
-
-      last = add_vuse_op (stmt, NULL, VEC_length (tree, new_ops), NULL);
-
-      for (i = 0; VEC_iterate (tree, new_ops, i, op); i++)
-       SET_USE (VUSE_OP_PTR (last, (int) i), op);
-
-      gimple_set_vuse_ops (stmt, last);
-      VEC_free (tree, heap, new_ops);
-    }
-
-#ifdef ENABLE_CHECKING
-  {
-    unsigned x;
-    
-    if (gimple_vuse_ops (stmt))
-      {
-       gcc_assert (gimple_vuse_ops (stmt)->next == NULL);
-       x = VUSE_NUM (gimple_vuse_ops (stmt));
-      }
-    else
-      x = 0;
-
-    gcc_assert (x == VEC_length (tree, build_vuses));
-  }
-#endif
-}
-
-/* Return a new VUSE operand vector for STMT.  */
-                                                                              
-static void
-finalize_ssa_vuses (gimple stmt)
-{
-  unsigned num, num_vdefs;
-  unsigned vuse_index;
-
-  /* Remove superfluous VUSE operands.  If the statement already has a
-     VDEF operator for a variable 'a', then a VUSE for 'a' is not
-     needed because VDEFs imply a VUSE of the variable.  For instance,
-     suppose that variable 'a' is pointed-to by p and q:
-
-             # VUSE <a_2>
-             # a_3 = VDEF <a_2>
-             *p = *q;
-
-     The VUSE <a_2> is superfluous because it is implied by the
-     VDEF operator.  */
-  num = VEC_length (tree, build_vuses);
-  num_vdefs = VEC_length (tree, build_vdefs);
-
-  if (num > 0 && num_vdefs > 0)
-    for (vuse_index = 0; vuse_index < VEC_length (tree, build_vuses); )
-      {
-       tree vuse;
-       vuse = VEC_index (tree, 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_vdef_list)
-             {
-               VEC_ordered_remove (tree, build_vuses, vuse_index);
-               continue;
-             }
-         }
-       vuse_index++;
-      }
-
-  finalize_ssa_vuse_ops (stmt);
 }
 
 
@@ -1024,23 +555,10 @@ finalize_ssa_vuses (gimple stmt)
 static inline void
 cleanup_build_arrays (void)
 {
-  unsigned i;
-  tree t;
-
-  for (i = 0; VEC_iterate (tree, build_vdefs, i, t); i++)
-    if (TREE_CODE (t) != SSA_NAME)
-      var_ann (t)->in_vdef_list = false;
-
-  for (i = 0; VEC_iterate (tree, build_vuses, i, t); i++)
-    if (TREE_CODE (t) != SSA_NAME)
-      var_ann (t)->in_vuse_list = false;
-
-  VEC_truncate (tree, build_vdefs, 0);
-  VEC_truncate (tree, build_vuses, 0);
+  build_vdef = NULL_TREE;
+  build_vuse = NULL_TREE;
   VEC_truncate (tree, build_defs, 0);
   VEC_truncate (tree, build_uses, 0);
-  bitmap_clear (build_loads);
-  bitmap_clear (build_stores);
 }
 
 
@@ -1051,11 +569,6 @@ finalize_ssa_stmt_operands (gimple stmt)
 {
   finalize_ssa_defs (stmt);
   finalize_ssa_uses (stmt);
-  if (gimple_has_mem_ops (stmt))
-    {
-      finalize_ssa_vdefs (stmt);
-      finalize_ssa_vuses (stmt);
-    }
   cleanup_build_arrays ();
 }
 
@@ -1067,10 +580,8 @@ start_ssa_stmt_operands (void)
 {
   gcc_assert (VEC_length (tree, build_defs) == 0);
   gcc_assert (VEC_length (tree, build_uses) == 0);
-  gcc_assert (VEC_length (tree, build_vuses) == 0);
-  gcc_assert (VEC_length (tree, build_vdefs) == 0);
-  gcc_assert (bitmap_empty_p (build_loads));
-  gcc_assert (bitmap_empty_p (build_stores));
+  gcc_assert (build_vuse == NULL_TREE);
+  gcc_assert (build_vdef == NULL_TREE);
 }
 
 
@@ -1097,31 +608,13 @@ append_use (tree *use_p)
 static inline void
 append_vdef (tree var)
 {
-  tree sym;
-
-  if (TREE_CODE (var) != SSA_NAME)
-    {
-      tree mpt;
-      var_ann_t ann;
+  gcc_assert ((build_vdef == NULL_TREE
+              || build_vdef == var)
+             && (build_vuse == NULL_TREE
+                 || build_vuse == var));
 
-      /* If VAR belongs to a memory partition, use it instead of VAR.  */
-      mpt = memory_partition (var);
-      if (mpt)
-       var = mpt;
-
-      /* Don't allow duplicate entries.  */
-      ann = get_var_ann (var);
-      if (ann->in_vdef_list)
-        return;
-
-      ann->in_vdef_list = true;
-      sym = var;
-    }
-  else
-    sym = SSA_NAME_VAR (var);
-
-  VEC_safe_push (tree, heap, build_vdefs, var);
-  bitmap_set_bit (build_stores, DECL_UID (sym));
+  build_vdef = var;
+  build_vuse = var;
 }
 
 
@@ -1130,303 +623,27 @@ append_vdef (tree var)
 static inline void
 append_vuse (tree var)
 {
-  tree sym;
-
-  if (TREE_CODE (var) != SSA_NAME)
-    {
-      tree mpt;
-      var_ann_t ann;
-
-      /* If VAR belongs to a memory partition, use it instead of VAR.  */
-      mpt = memory_partition (var);
-      if (mpt)
-       var = mpt;
-
-      /* Don't allow duplicate entries.  */
-      ann = get_var_ann (var);
-      if (ann->in_vuse_list)
-       return;
-      else if (ann->in_vdef_list)
-       {
-         /* We don't want a vuse if we already have a vdef, but we must
-            still put this in build_loads.  */
-         bitmap_set_bit (build_loads, DECL_UID (var));
-         return;
-       }
-
-      ann->in_vuse_list = true;
-      sym = var;
-    }
-  else
-    sym = SSA_NAME_VAR (var);
-
-  VEC_safe_push (tree, heap, build_vuses, var);
-  bitmap_set_bit (build_loads, DECL_UID (sym));
-}
-
-
-/* REF is a tree that contains the entire pointer dereference
-   expression, if available, or NULL otherwise.  ALIAS is the variable
-   we are asking if REF can access.  OFFSET and SIZE come from the
-   memory access expression that generated this virtual operand.
-
-   XXX: We should handle the NO_ALIAS attributes here.  */
-
-static bool
-access_can_touch_variable (tree ref, tree alias, HOST_WIDE_INT offset,
-                          HOST_WIDE_INT size)
-{
-  bool offsetgtz = offset > 0;
-  unsigned HOST_WIDE_INT uoffset = (unsigned HOST_WIDE_INT) offset;
-  tree base = ref ? get_base_address (ref) : NULL;
-
-  /* If ALIAS is .GLOBAL_VAR then the memory reference REF must be
-     using a call-clobbered memory tag.  By definition, call-clobbered
-     memory tags can always touch .GLOBAL_VAR.  */
-  if (alias == gimple_global_var (cfun))
-    return true;
-
-  /* If ref is a TARGET_MEM_REF, just return true, as we can't really
-     disambiguate them right now.  */
-  if (ref && TREE_CODE (ref) == TARGET_MEM_REF)
-    return true;
-  
-  /* Without strict aliasing, it is impossible for a component access
-     through a pointer to touch a random variable, unless that
-     variable *is* a structure or a pointer.
-
-     That is, given p->c, and some random global variable b,
-     there is no legal way that p->c could be an access to b.
-     
-     Without strict aliasing on, we consider it legal to do something
-     like:
-
-     struct foos { int l; };
-     int foo;
-     static struct foos *getfoo(void);
-     int main (void)
-     {
-       struct foos *f = getfoo();
-       f->l = 1;
-       foo = 2;
-       if (f->l == 1)
-         abort();
-       exit(0);
-     }
-     static struct foos *getfoo(void)     
-     { return (struct foos *)&foo; }
-     
-     (taken from 20000623-1.c)
-
-     The docs also say/imply that access through union pointers
-     is legal (but *not* if you take the address of the union member,
-     i.e. the inverse), such that you can do
-
-     typedef union {
-       int d;
-     } U;
-
-     int rv;
-     void breakme()
-     {
-       U *rv0;
-       U *pretmp = (U*)&rv;
-       rv0 = pretmp;
-       rv0->d = 42;    
-     }
-     To implement this, we just punt on accesses through union
-     pointers entirely.
-
-     Another case we have to allow is accessing a variable
-     through an array access at offset zero.  This happens from
-     code generated by the fortran frontend like
-
-     char[1:1] & my_char_ref;
-     char my_char;
-     my_char_ref_1 = (char[1:1] &) &my_char;
-     D.874_2 = (*my_char_ref_1)[1]{lb: 1 sz: 1};
-  */
-  if (ref 
-      && flag_strict_aliasing
-      && TREE_CODE (ref) != INDIRECT_REF
-      && !MTAG_P (alias)
-      && base
-      && (TREE_CODE (base) != INDIRECT_REF
-         || TREE_CODE (TREE_TYPE (base)) != UNION_TYPE)
-      && (TREE_CODE (base) != INDIRECT_REF
-         || TREE_CODE (ref) != ARRAY_REF
-         || offset != 0
-         || (DECL_SIZE (alias)
-             && TREE_CODE (DECL_SIZE (alias)) == INTEGER_CST
-             && size != -1
-             && (unsigned HOST_WIDE_INT)size
-             != TREE_INT_CST_LOW (DECL_SIZE (alias))))
-      && !AGGREGATE_TYPE_P (TREE_TYPE (alias))
-      && TREE_CODE (TREE_TYPE (alias)) != COMPLEX_TYPE
-      && !var_ann (alias)->is_heapvar
-      /* When the struct has may_alias attached to it, we need not to
-        return true.  */
-      && get_alias_set (base))
-    {
-#ifdef ACCESS_DEBUGGING
-      fprintf (stderr, "Access to ");
-      print_generic_expr (stderr, ref, 0);
-      fprintf (stderr, " may not touch ");
-      print_generic_expr (stderr, alias, 0);
-      fprintf (stderr, " in function %s\n", get_name (current_function_decl));
-#endif
-      return false;
-    }
-
-  /* If the offset of the access is greater than the size of one of
-     the possible aliases, it can't be touching that alias, because it
-     would be past the end of the structure.  */
-  else if (ref
-          && flag_strict_aliasing
-          && TREE_CODE (ref) != INDIRECT_REF
-          && !MTAG_P (alias)
-          && !var_ann (alias)->is_heapvar
-          && !POINTER_TYPE_P (TREE_TYPE (alias))
-          && offsetgtz
-          && DECL_SIZE (alias)
-          && TREE_CODE (DECL_SIZE (alias)) == INTEGER_CST
-          && uoffset >= TREE_INT_CST_LOW (DECL_SIZE (alias)))
-    {
-#ifdef ACCESS_DEBUGGING
-      fprintf (stderr, "Access to ");
-      print_generic_expr (stderr, ref, 0);
-      fprintf (stderr, " may not touch ");
-      print_generic_expr (stderr, alias, 0);
-      fprintf (stderr, " in function %s\n", get_name (current_function_decl));
-#endif
-      return false;
-    }     
+  gcc_assert (build_vuse == NULL_TREE
+             || build_vuse == var);
 
-  return true;
+  build_vuse = var;
 }
 
-/* Add VAR to the virtual operands for STMT.  FLAGS is as in
-   get_expr_operands.  FULL_REF is a tree that contains the entire
-   pointer dereference expression, if available, or NULL otherwise.
-   OFFSET and SIZE come from the memory access expression that
-   generated this virtual operand.  IS_CALL_SITE is true if the
-   affected statement is a call site.  */
-
-static void
-add_virtual_operand (tree var, gimple stmt, int flags,
-                    tree full_ref, HOST_WIDE_INT offset,
-                    HOST_WIDE_INT size, bool is_call_site)
-{
-  bitmap aliases = NULL;
-  tree sym;
-  var_ann_t v_ann;
-  
-  sym = (TREE_CODE (var) == SSA_NAME ? SSA_NAME_VAR (var) : var);
-  v_ann = var_ann (sym);
-  
-  /* Mark the statement as having memory operands.  */
-  gimple_set_references_memory (stmt, true);
-
-  /* If the variable cannot be modified and this is a VDEF change
-     it into a VUSE.  This happens when read-only variables are marked
-     call-clobbered and/or aliased to writable variables.  So we only
-     check that this only happens on non-specific stores.
-
-     Note that if this is a specific store, i.e. associated with a
-     MODIFY_EXPR, then we can't suppress the VDEF, lest we run
-     into validation problems.
-
-     This can happen when programs cast away const, leaving us with a
-     store to read-only memory.  If the statement is actually executed
-     at runtime, then the program is ill formed.  If the statement is
-     not executed then all is well.  At the very least, we cannot ICE.  */
-  if ((flags & opf_implicit) && unmodifiable_var_p (var))
-    flags &= ~opf_def;
-  
-  /* The variable is not a GIMPLE register.  Add it (or its aliases) to
-     virtual operands, unless the caller has specifically requested
-     not to add virtual operands (used when adding operands inside an
-     ADDR_EXPR expression).  */
-  if (flags & opf_no_vops)
-    return;
-  
-  if (MTAG_P (var))
-    aliases = MTAG_ALIASES (var);
-
-  if (aliases == NULL)
-    {
-      if (!gimple_aliases_computed_p (cfun) && (flags & opf_def))
-       gimple_set_has_volatile_ops (stmt, true);
-
-      /* The variable is not aliased or it is an alias tag.  */
-      if (flags & opf_def)
-       append_vdef (var);
-      else
-       append_vuse (var);
-    }
-  else
-    {
-      bitmap_iterator bi;
-      unsigned int i;
-      bool none_added = true;
-      
-      /* The variable is aliased.  Add its aliases to the virtual
-        operands.  */
-      gcc_assert (!bitmap_empty_p (aliases));
-
-      EXECUTE_IF_SET_IN_BITMAP (aliases, 0, i, bi)
-       {
-         tree al = referenced_var (i);
-
-         /* Call-clobbered tags may have non-call-clobbered
-            symbols in their alias sets.  Ignore them if we are
-            adding VOPs for a call site.  */
-         if (is_call_site && !is_call_clobbered (al))
-           continue;
-
-         /* If we do not know the full reference tree or if the access is
-            unspecified [0, -1], we cannot prune it.  Otherwise try doing
-            so using access_can_touch_variable.  */
-         if (full_ref
-             && !access_can_touch_variable (full_ref, al, offset, size))
-           continue;
-
-         if (flags & opf_def)
-           append_vdef (al);
-         else
-           append_vuse (al);
-         none_added = false;
-       }
+/* Add virtual operands for STMT.  FLAGS is as in get_expr_operands.  */
 
-      if (flags & opf_def)
-       {
-         /* If the variable is also an alias tag, add a virtual
-            operand for it, otherwise we will miss representing
-            references to the members of the variable's alias set.          
-            This fixes the bug in gcc.c-torture/execute/20020503-1.c.
-            
-            It is also necessary to add bare defs on clobbers for
-            SMT's, so that bare SMT uses caused by pruning all the
-            aliases will link up properly with calls.   In order to
-            keep the number of these bare defs we add down to the
-            minimum necessary, we keep track of which SMT's were used
-            alone in statement vdefs or VUSEs.  */
-         if (none_added
-             || (TREE_CODE (var) == SYMBOL_MEMORY_TAG
-                 && is_call_site))
-           append_vdef (var);
-       }
-      else
-       {
-         /* Even if no aliases have been added, we still need to
-            establish def-use and use-def chains, lest
-            transformations think that this is not a memory
-            reference.  For an example of this scenario, see
-            testsuite/g++.dg/opt/cleanup1.C.  */
-         if (none_added)
-           append_vuse (var);
-       }
-    }
+static void
+add_virtual_operand (gimple stmt ATTRIBUTE_UNUSED, int flags)
+{
+  /* Add virtual operands to the stmt, unless the caller has specifically
+     requested not to do that (used when adding operands inside an
+     ADDR_EXPR expression).  */
+  if (flags & opf_no_vops)
+    return;
+
+  if (flags & opf_def)
+    append_vdef (gimple_vop (cfun));
+  else
+    append_vuse (gimple_vop (cfun));
 }
 
 
@@ -1460,106 +677,43 @@ add_stmt_operand (tree *var_p, gimple stmt, int flags)
        append_use (var_p);
     }
   else
-    add_virtual_operand (var, stmt, flags, NULL_TREE, 0, -1, false);
+    add_virtual_operand (stmt, flags);
 }
 
-/* Subroutine of get_indirect_ref_operands.  ADDR is the address
-   that is dereferenced, the meaning of the rest of the arguments
-   is the same as in get_indirect_ref_operands.  */
+/* Add the base address of REF to SET.  */
 
 static void
-get_addr_dereference_operands (gimple stmt, tree *addr, int flags,
-                              tree full_ref, HOST_WIDE_INT offset,
-                              HOST_WIDE_INT size, bool recurse_on_base)
+add_to_addressable_set (tree ref, bitmap *set)
 {
-  tree ptr = *addr;
-
-  /* Mark the statement as having memory operands.  */
-  gimple_set_references_memory (stmt, true);
+  tree var;
 
-  if (SSA_VAR_P (ptr))
+  /* Note that it is *NOT OKAY* to use the target of a COMPONENT_REF
+     as the only thing we take the address of.  If VAR is a structure,
+     taking the address of a field means that the whole structure may
+     be referenced using pointer arithmetic.  See PR 21407 and the
+     ensuing mailing list discussion.  */
+  var = get_base_address (ref);
+  if (var && SSA_VAR_P (var))
     {
-      struct ptr_info_def *pi = NULL;
+      if (*set == NULL)
+       *set = BITMAP_ALLOC (&operands_bitmap_obstack);
 
-      /* If PTR has flow-sensitive points-to information, use it.  */
-      if (TREE_CODE (ptr) == SSA_NAME
-         && (pi = SSA_NAME_PTR_INFO (ptr)) != NULL
-         && pi->name_mem_tag)
-       {
-         /* PTR has its own memory tag.  Use it.  */
-         add_virtual_operand (pi->name_mem_tag, stmt, flags,
-                              full_ref, offset, size, false);
-       }
-      else
-       {
-         /* If PTR is not an SSA_NAME or it doesn't have a name
-            tag, use its symbol memory tag.  */
-         var_ann_t v_ann;
-
-         /* If we are emitting debugging dumps, display a warning if
-            PTR is an SSA_NAME with no flow-sensitive alias
-            information.  That means that we may need to compute
-            aliasing again or that a propagation pass forgot to
-            update the alias information on the pointers.  */
-         if (dump_file
-             && TREE_CODE (ptr) == SSA_NAME
-             && (pi == NULL
-                 || (pi->name_mem_tag == NULL_TREE
-                     && !pi->pt_anything))
-             && gimple_aliases_computed_p (cfun))
-           {
-             fprintf (dump_file,
-                 "NOTE: no flow-sensitive alias info for ");
-             print_generic_expr (dump_file, ptr, dump_flags);
-             fprintf (dump_file, " in ");
-             print_gimple_stmt (dump_file, stmt, 0, 0);
-           }
-
-         if (TREE_CODE (ptr) == SSA_NAME)
-           ptr = SSA_NAME_VAR (ptr);
-         v_ann = var_ann (ptr);
-
-         /* If we don't know what this pointer points to then we have
-            to make sure to not prune virtual operands based on offset
-            and size.  */
-         if (v_ann->symbol_mem_tag)
-           {
-             add_virtual_operand (v_ann->symbol_mem_tag, stmt, flags,
-                                  full_ref, 0, -1, false);
-             /* Make sure we add the SMT itself.  */
-             if (!(flags & opf_no_vops))
-               {
-                 if (flags & opf_def)
-                   append_vdef (v_ann->symbol_mem_tag);
-                 else
-                   append_vuse (v_ann->symbol_mem_tag);
-               }
-           }
-
-         /* Aliasing information is missing; mark statement as
-            volatile so we won't optimize it out too actively.  */
-          else if (!gimple_aliases_computed_p (cfun)
-                   && (flags & opf_def))
-           gimple_set_has_volatile_ops (stmt, true);
-       }
-    }
-  else if (TREE_CODE (ptr) == INTEGER_CST)
-    {
-      /* If a constant is used as a pointer, we can't generate a real
-        operand for it but we mark the statement volatile to prevent
-        optimizations from messing things up.  */
-      gimple_set_has_volatile_ops (stmt, true);
-      return;
-    }
-  else
-    {
-      /* Ok, this isn't even is_gimple_min_invariant.  Something's broke.  */
-      gcc_unreachable ();
+      bitmap_set_bit (*set, DECL_UID (var));
+      TREE_ADDRESSABLE (var) = 1;
     }
+}
 
-  /* If requested, add a USE operand for the base pointer.  */
-  if (recurse_on_base)
-    get_expr_operands (stmt, addr, opf_use);
+/* Add the base address of REF to the set of addresses taken by STMT.
+   REF may be a single variable whose address has been taken or any
+   other valid GIMPLE memory reference (structure reference, array,
+   etc).  If the base address of REF is a decl that has sub-variables,
+   also add all of its sub-variables.  */
+
+static void
+gimple_add_to_addresses_taken (gimple stmt, tree ref)
+{
+  gcc_assert (gimple_has_ops (stmt));
+  add_to_addressable_set (ref, gimple_addresses_taken_ptr (stmt));
 }
 
 
@@ -1571,19 +725,12 @@ get_addr_dereference_operands (gimple stmt, tree *addr, int flags,
    
    FLAGS is as in get_expr_operands.
 
-   FULL_REF contains the full pointer dereference expression, if we
-      have it, or NULL otherwise.
-
-   OFFSET and SIZE are the location of the access inside the
-      dereferenced pointer, if known.
-
    RECURSE_ON_BASE should be set to true if we want to continue
       calling get_expr_operands on the base pointer, and false if
       something else will do it for us.  */
 
 static void
-get_indirect_ref_operands (gimple stmt, tree expr, int flags, tree full_ref,
-                          HOST_WIDE_INT offset, HOST_WIDE_INT size,
+get_indirect_ref_operands (gimple stmt, tree expr, int flags,
                           bool recurse_on_base)
 {
   tree *pptr = &TREE_OPERAND (expr, 0);
@@ -1591,8 +738,12 @@ get_indirect_ref_operands (gimple stmt, tree expr, int flags, tree full_ref,
   if (TREE_THIS_VOLATILE (expr))
     gimple_set_has_volatile_ops (stmt, true);
 
-  get_addr_dereference_operands (stmt, pptr, flags, full_ref, offset, size,
-                                recurse_on_base);
+  /* Add the VOP.  */
+  add_virtual_operand (stmt, flags);
+
+  /* If requested, add a USE operand for the base pointer.  */
+  if (recurse_on_base)
+    get_expr_operands (stmt, pptr, opf_use);
 }
 
 
@@ -1601,11 +752,6 @@ get_indirect_ref_operands (gimple stmt, tree expr, int flags, tree full_ref,
 static void
 get_tmr_operands (gimple stmt, tree expr, int flags)
 {
-  tree tag;
-
-  /* Mark the statement as having memory operands.  */
-  gimple_set_references_memory (stmt, true);
-
   /* First record the real operands.  */
   get_expr_operands (stmt, &TMR_BASE (expr), opf_use);
   get_expr_operands (stmt, &TMR_INDEX (expr), opf_use);
@@ -1613,154 +759,7 @@ get_tmr_operands (gimple stmt, tree expr, int flags)
   if (TMR_SYMBOL (expr))
     gimple_add_to_addresses_taken (stmt, TMR_SYMBOL (expr));
 
-  tag = TMR_TAG (expr);
-  if (!tag)
-    {
-      /* Something weird, so ensure that we will be careful.  */
-      gimple_set_has_volatile_ops (stmt, true);
-      return;
-    }
-  if (!MTAG_P (tag))
-    {
-      get_expr_operands (stmt, &tag, flags);
-      return;
-    }
-
-  add_virtual_operand (tag, stmt, flags, expr, 0, -1, false);
-}
-
-
-/* Add clobbering definitions for .GLOBAL_VAR or for each of the call
-   clobbered variables in the function.  */
-
-static void
-add_call_clobber_ops (gimple stmt, tree callee ATTRIBUTE_UNUSED)
-{
-  unsigned u;
-  bitmap_iterator bi;
-  bitmap not_read_b, not_written_b;
-
-  gcc_assert (!(gimple_call_flags (stmt) & (ECF_PURE | ECF_CONST)));
-
-  /* If we created .GLOBAL_VAR earlier, just use it.  */
-  if (gimple_global_var (cfun))
-    {
-      tree var = gimple_global_var (cfun);
-      add_virtual_operand (var, stmt, opf_def, NULL, 0, -1, true);
-      return;
-    }
-
-  /* Get info for local and module level statics.  There is a bit
-     set for each static if the call being processed does not read
-     or write that variable.  */
-  not_read_b = callee ? ipa_reference_get_not_read_global (cgraph_node (callee)) : NULL; 
-  not_written_b = callee ? ipa_reference_get_not_written_global (cgraph_node (callee)) : NULL;
-
-  /* Add a VDEF operand for every call clobbered variable.  */
-  EXECUTE_IF_SET_IN_BITMAP (gimple_call_clobbered_vars (cfun), 0, u, bi)
-    {
-      tree var = referenced_var_lookup (u);
-      tree real_var = var;
-      bool not_read;
-      bool not_written;
-
-      not_read = not_read_b
-                ? bitmap_bit_p (not_read_b, DECL_UID (real_var))
-                : false;
-
-      not_written = not_written_b
-                   ? bitmap_bit_p (not_written_b, DECL_UID (real_var))
-                   : false;
-      gcc_assert (!unmodifiable_var_p (var));
-      
-      clobber_stats.clobbered_vars++;
-
-      /* See if this variable is really clobbered by this function.  */
-
-      if (not_written)
-       {
-         clobber_stats.static_write_clobbers_avoided++;
-         if (!not_read)
-           add_virtual_operand (var, stmt, opf_use, NULL, 0, -1, true);
-         else
-           clobber_stats.static_read_clobbers_avoided++;
-       }
-      else
-       add_virtual_operand (var, stmt, opf_def, NULL, 0, -1, true);
-    }
-}
-
-
-/* Add VUSE operands for .GLOBAL_VAR or all call clobbered variables in the
-   function.  */
-
-static void
-add_call_read_ops (gimple stmt, tree callee ATTRIBUTE_UNUSED)
-{
-  unsigned u;
-  bitmap_iterator bi;
-  bitmap not_read_b;
-
-  /* Const functions do not reference memory.  */
-  if (gimple_call_flags (stmt) & ECF_CONST)
-    return;
-
-  not_read_b = callee ? ipa_reference_get_not_read_global (cgraph_node (callee)) : NULL;
-
-  /* For pure functions we compute non-escaped uses separately.  */
-  if (gimple_call_flags (stmt) & ECF_PURE)
-    EXECUTE_IF_SET_IN_BITMAP (gimple_call_used_vars (cfun), 0, u, bi)
-      {
-       tree var = referenced_var_lookup (u);
-       tree real_var = var;
-       bool not_read;
-
-       if (unmodifiable_var_p (var))
-         continue;
-
-       not_read = not_read_b
-           ? bitmap_bit_p (not_read_b, DECL_UID (real_var))
-           : false;
-
-       clobber_stats.readonly_clobbers++;
-
-       /* See if this variable is really used by this function.  */
-       if (!not_read)
-         add_virtual_operand (var, stmt, opf_use, NULL, 0, -1, true);
-       else
-         clobber_stats.static_readonly_clobbers_avoided++;
-      }
-
-  /* Add a VUSE for .GLOBAL_VAR if it has been created.  See
-     add_referenced_var for the heuristic used to decide whether to
-     create .GLOBAL_VAR.  */
-  if (gimple_global_var (cfun))
-    {
-      tree var = gimple_global_var (cfun);
-      add_virtual_operand (var, stmt, opf_use, NULL, 0, -1, true);
-      return;
-    }
-
-  /* Add a VUSE for each call-clobbered variable.  */
-  EXECUTE_IF_SET_IN_BITMAP (gimple_call_clobbered_vars (cfun), 0, u, bi)
-    {
-      tree var = referenced_var (u);
-      tree real_var = var;
-      bool not_read;
-      
-      clobber_stats.readonly_clobbers++;
-
-      not_read = not_read_b ? bitmap_bit_p (not_read_b, DECL_UID (real_var))
-                           : false;
-      
-      if (not_read)
-       {
-         clobber_stats.static_readonly_clobbers_avoided++;
-         continue;
-       }
-            
-      add_virtual_operand (var, stmt, opf_use, NULL, 0, -1, true);
-    }
+  add_virtual_operand (stmt, flags);
 }
 
 
@@ -1768,25 +767,22 @@ add_call_read_ops (gimple stmt, tree callee ATTRIBUTE_UNUSED)
    escape, add them to the VDEF/VUSE lists for it.  */
 
 static void
-maybe_add_call_clobbered_vops (gimple stmt)
+maybe_add_call_vops (gimple stmt)
 {
   int call_flags = gimple_call_flags (stmt);
 
-  /* Mark the statement as having memory operands.  */
-  gimple_set_references_memory (stmt, true);
-
   /* If aliases have been computed already, add VDEF or VUSE
      operands for all the symbols that have been found to be
      call-clobbered.  */
-  if (gimple_aliases_computed_p (cfun) && !(call_flags & ECF_NOVOPS))
+  if (!(call_flags & ECF_NOVOPS))
     {
       /* A 'pure' or a 'const' function never call-clobbers anything. 
         A 'noreturn' function might, but since we don't return anyway 
         there is no point in recording that.  */ 
       if (!(call_flags & (ECF_PURE | ECF_CONST | ECF_NORETURN)))
-       add_call_clobber_ops (stmt, gimple_call_fndecl (stmt));
+       add_virtual_operand (stmt, opf_def);
       else if (!(call_flags & ECF_CONST))
-       add_call_read_ops (stmt, gimple_call_fndecl (stmt));
+       add_virtual_operand (stmt, opf_use);
     }
 }
 
@@ -1854,23 +850,7 @@ get_asm_expr_operands (gimple stmt)
       tree link = gimple_asm_clobber_op (stmt, i);
       if (strcmp (TREE_STRING_POINTER (TREE_VALUE (link)), "memory") == 0)
        {
-         unsigned i;
-         bitmap_iterator bi;
-
-         /* Mark the statement as having memory operands.  */
-         gimple_set_references_memory (stmt, true);
-
-         EXECUTE_IF_SET_IN_BITMAP (gimple_call_clobbered_vars (cfun), 0, i, bi)
-           {
-             tree var = referenced_var (i);
-             add_stmt_operand (&var, stmt, opf_def | opf_implicit);
-           }
-
-         EXECUTE_IF_SET_IN_BITMAP (gimple_addressable_vars (cfun), 0, i, bi)
-           {
-             tree var = referenced_var (i);
-             add_stmt_operand (&var, stmt, opf_def | opf_implicit);
-           }
+         add_virtual_operand (stmt, opf_def);
          break;
        }
     }
@@ -1918,8 +898,6 @@ get_expr_operands (gimple stmt, tree *expr_p, int flags)
       return;
 
     case SSA_NAME:
-    case SYMBOL_MEMORY_TAG:
-    case NAME_MEMORY_TAG:
      add_stmt_operand (expr_p, stmt, flags);
      return;
 
@@ -1935,7 +913,7 @@ get_expr_operands (gimple stmt, tree *expr_p, int flags)
 
     case ALIGN_INDIRECT_REF:
     case INDIRECT_REF:
-      get_indirect_ref_operands (stmt, expr, flags, expr, 0, -1, true);
+      get_indirect_ref_operands (stmt, expr, flags, true);
       return;
 
     case TARGET_MEM_REF:
@@ -1957,8 +935,7 @@ get_expr_operands (gimple stmt, tree *expr_p, int flags)
        ref = get_ref_base_and_extent (expr, &offset, &size, &maxsize);
        if (TREE_CODE (ref) == INDIRECT_REF)
          {
-           get_indirect_ref_operands (stmt, ref, flags, expr, offset,
-                                      maxsize, false);
+           get_indirect_ref_operands (stmt, ref, flags, false);
            flags |= opf_no_vops;
          }
 
@@ -2098,7 +1075,7 @@ parse_ssa_operands (gimple stmt)
 
       /* Add call-clobbered operands, if needed.  */
       if (code == GIMPLE_CALL)
-       maybe_add_call_clobbered_vops (stmt);
+       maybe_add_call_vops (stmt);
     }
 }
 
@@ -2111,7 +1088,6 @@ build_ssa_operands (gimple stmt)
   /* Initially assume that the statement has no volatile operands and
      makes no memory references.  */
   gimple_set_has_volatile_ops (stmt, false);
-  gimple_set_references_memory (stmt, false);
 
   /* Just clear the bitmap so we don't end up reallocating it over and over.  */
   if (gimple_addresses_taken (stmt))
@@ -2119,14 +1095,7 @@ build_ssa_operands (gimple stmt)
 
   start_ssa_stmt_operands ();
   parse_ssa_operands (stmt);
-  operand_build_sort_virtual (build_vuses);
-  operand_build_sort_virtual (build_vdefs);
   finalize_ssa_stmt_operands (stmt);
-
-  /* For added safety, assume that statements with volatile operands
-     also reference memory.  */
-  if (gimple_has_volatile_ops (stmt))
-    gimple_set_references_memory (stmt, true);
 }
 
 
@@ -2138,9 +1107,6 @@ free_stmt_operands (gimple stmt)
 {
   def_optype_p defs = gimple_def_ops (stmt), last_def;
   use_optype_p uses = gimple_use_ops (stmt), last_use;
-  voptype_p vuses = gimple_vuse_ops (stmt);
-  voptype_p vdefs = gimple_vdef_ops (stmt), vdef, next_vdef;
-  unsigned i;
 
   if (defs)
     {
@@ -2161,32 +1127,13 @@ free_stmt_operands (gimple stmt)
       gimple_set_use_ops (stmt, NULL);
     }
 
-  if (vuses)
-    {
-      for (i = 0; i < VUSE_NUM (vuses); i++)
-       delink_imm_use (VUSE_OP_PTR (vuses, i));
-      add_vop_to_freelist (vuses);
-      gimple_set_vuse_ops (stmt, NULL);
-    }
-
-  if (vdefs)
-    {
-      for (vdef = vdefs; vdef; vdef = next_vdef)
-       {
-         next_vdef = vdef->next;
-         delink_imm_use (VDEF_OP_PTR (vdef, 0));
-         add_vop_to_freelist (vdef);
-       }
-      gimple_set_vdef_ops (stmt, NULL);
-    }
-
   if (gimple_has_ops (stmt))
     gimple_set_addresses_taken (stmt, NULL);
 
   if (gimple_has_mem_ops (stmt))
     {
-      gimple_set_stored_syms (stmt, NULL, &operands_bitmap_obstack);
-      gimple_set_loaded_syms (stmt, NULL, &operands_bitmap_obstack);
+      gimple_set_vuse (stmt, NULL_TREE);
+      gimple_set_vdef (stmt, NULL_TREE);
     }
 }
 
@@ -2211,113 +1158,6 @@ update_stmt_operands (gimple stmt)
 }
 
 
-/* Copies virtual operands from SRC to DST.  */
-
-void
-copy_virtual_operands (gimple dest, gimple src)
-{
-  unsigned int i, n;
-  voptype_p src_vuses, dest_vuses;
-  voptype_p src_vdefs, dest_vdefs;
-  struct voptype_d vuse;
-  struct voptype_d vdef;
-
-  if (!gimple_has_mem_ops (src))
-    return;
-
-  gimple_set_vdef_ops (dest, NULL);
-  gimple_set_vuse_ops (dest, NULL);
-
-  gimple_set_stored_syms (dest, gimple_stored_syms (src),
-                         &operands_bitmap_obstack);
-  gimple_set_loaded_syms (dest, gimple_loaded_syms (src),
-                         &operands_bitmap_obstack);
-
-  /* Copy all the VUSE operators and corresponding operands.  */
-  dest_vuses = &vuse;
-  for (src_vuses = gimple_vuse_ops (src);
-       src_vuses;
-       src_vuses = src_vuses->next)
-    {
-      n = VUSE_NUM (src_vuses);
-      dest_vuses = add_vuse_op (dest, NULL_TREE, n, dest_vuses);
-      for (i = 0; i < n; i++)
-       SET_USE (VUSE_OP_PTR (dest_vuses, i), VUSE_OP (src_vuses, i));
-
-      if (gimple_vuse_ops (dest) == NULL)
-       gimple_set_vuse_ops (dest, vuse.next);
-    }
-
-  /* Copy all the VDEF operators and corresponding operands.  */
-  dest_vdefs = &vdef;
-  for (src_vdefs = gimple_vdef_ops (src);
-       src_vdefs;
-       src_vdefs = src_vdefs->next)
-    {
-      n = VUSE_NUM (src_vdefs);
-      dest_vdefs = add_vdef_op (dest, NULL_TREE, n, dest_vdefs);
-      VDEF_RESULT (dest_vdefs) = VDEF_RESULT (src_vdefs);
-      for (i = 0; i < n; i++)
-       SET_USE (VUSE_OP_PTR (dest_vdefs, i), VUSE_OP (src_vdefs, i));
-
-      if (gimple_vdef_ops (dest) == NULL)
-       gimple_set_vdef_ops (dest, vdef.next);
-    }
-}
-
-
-/* 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.  If DELINK_IMM_USES_P is specified, the immediate
-   uses of this stmt will be de-linked.  */
-
-void
-create_ssa_artificial_load_stmt (gimple new_stmt, gimple old_stmt,
-                                bool delink_imm_uses_p)
-{
-  tree op;
-  ssa_op_iter iter;
-  use_operand_p use_p;
-  unsigned i;
-
-  gimple_set_modified (new_stmt, false);
-
-  /* Process NEW_STMT looking for operands.  */
-  start_ssa_stmt_operands ();
-  parse_ssa_operands (new_stmt);
-
-  for (i = 0; VEC_iterate (tree, build_vuses, i, op); i++)
-    if (TREE_CODE (op) != SSA_NAME)
-      var_ann (op)->in_vuse_list = false;
-   
-  for (i = 0; VEC_iterate (tree, build_vdefs, i, op); i++)
-    if (TREE_CODE (op) != SSA_NAME)
-      var_ann (op)->in_vdef_list = false;
-
-  /* Remove any virtual operands that were found.  */
-  VEC_truncate (tree, build_vdefs, 0);
-  VEC_truncate (tree, build_vuses, 0);
-
-  /* Clear the loads and stores bitmaps.  */
-  bitmap_clear (build_loads);
-  bitmap_clear (build_stores);
-
-  /* For each VDEF on the original statement, we want to create a
-     VUSE of the VDEF result operand on the new statement.  */
-  FOR_EACH_SSA_TREE_OPERAND (op, old_stmt, iter, SSA_OP_VDEF)
-    append_vuse (op);
-
-  finalize_ssa_stmt_operands (new_stmt);
-
-  /* All uses in this fake stmt must not be in the immediate use lists.  */
-  if (delink_imm_uses_p)
-    FOR_EACH_SSA_USE_OPERAND (use_p, new_stmt, iter, SSA_OP_ALL_USES)
-      delink_imm_use (use_p);
-}
-
-
 /* Swap operands EXP0 and EXP1 in statement STMT.  No attempt is done
    to test the validity of the swap operation.  */
 
@@ -2366,43 +1206,6 @@ swap_tree_operands (gimple stmt, tree *exp0, tree *exp1)
   *exp1 = op0;
 }
 
-/* Add the base address of REF to SET.  */
-
-void
-add_to_addressable_set (tree ref, bitmap *set)
-{
-  tree var;
-
-  /* Note that it is *NOT OKAY* to use the target of a COMPONENT_REF
-     as the only thing we take the address of.  If VAR is a structure,
-     taking the address of a field means that the whole structure may
-     be referenced using pointer arithmetic.  See PR 21407 and the
-     ensuing mailing list discussion.  */
-  var = get_base_address (ref);
-  if (var && SSA_VAR_P (var))
-    {
-      if (*set == NULL)
-       *set = BITMAP_ALLOC (&operands_bitmap_obstack);
-
-      bitmap_set_bit (*set, DECL_UID (var));
-      TREE_ADDRESSABLE (var) = 1;
-    }
-}
-
-
-/* Add the base address of REF to the set of addresses taken by STMT.
-   REF may be a single variable whose address has been taken or any
-   other valid GIMPLE memory reference (structure reference, array,
-   etc).  If the base address of REF is a decl that has sub-variables,
-   also add all of its sub-variables.  */
-
-void
-gimple_add_to_addresses_taken (gimple stmt, tree ref)
-{
-  gcc_assert (gimple_has_ops (stmt));
-  add_to_addressable_set (ref, gimple_addresses_taken_ptr (stmt));
-}
-
 
 /* Scan the immediate_use list for VAR making sure its linked properly.
    Return TRUE if there is a problem and emit an error message to F.  */
@@ -2547,192 +1350,94 @@ debug_immediate_uses_for (tree var)
 }
 
 
-/* Create a new change buffer for the statement pointed by STMT_P and
-   push the buffer into SCB_STACK.  Each change buffer
-   records state information needed to determine what changed in the
-   statement.  Mainly, this keeps track of symbols that may need to be
-   put into SSA form, SSA name replacements and other information
-   needed to keep the SSA form up to date.  */
+/* Push *STMT_P on the SCB_STACK.  This function is deprecated, do not
+   introduce new uses of it.  */
 
 void
 push_stmt_changes (gimple *stmt_p)
 {
-  gimple stmt;
-  scb_t buf;
-
-  stmt = *stmt_p;
+  gimple stmt = *stmt_p;
 
   /* It makes no sense to keep track of PHI nodes.  */
   if (gimple_code (stmt) == GIMPLE_PHI)
     return;
 
-  buf = XNEW (struct scb_d);
-  memset (buf, 0, sizeof *buf);
-
-  buf->stmt_p = stmt_p;
-
-  if (gimple_references_memory_p (stmt))
-    {
-      tree op;
-      ssa_op_iter i;
-
-      FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_VUSE)
-       {
-         tree sym = TREE_CODE (op) == SSA_NAME ? SSA_NAME_VAR (op) : op;
-         if (buf->loads == NULL)
-           buf->loads = BITMAP_ALLOC (NULL);
-         bitmap_set_bit (buf->loads, DECL_UID (sym));
-       }
-
-      FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_VDEF)
-       {
-         tree sym = TREE_CODE (op) == SSA_NAME ? SSA_NAME_VAR (op) : op;
-         if (buf->stores == NULL)
-           buf->stores = BITMAP_ALLOC (NULL);
-         bitmap_set_bit (buf->stores, DECL_UID (sym));
-       }
-    }
-
-  VEC_safe_push (scb_t, heap, scb_stack, buf);
-}
-
-
-/* Given two sets S1 and S2, mark the symbols that differ in S1 and S2
-   for renaming.  The set to mark for renaming is (S1 & ~S2) | (S2 & ~S1).  */
-
-static void
-mark_difference_for_renaming (bitmap s1, bitmap s2)
-{
-  if (s1 == NULL && s2 == NULL)
-    return;
-
-  if (s1 && s2 == NULL)
-    mark_set_for_renaming (s1);
-  else if (s1 == NULL && s2)
-    mark_set_for_renaming (s2);
-  else if (!bitmap_equal_p (s1, s2))
-    {
-      bitmap t1 = BITMAP_ALLOC (NULL);
-      bitmap_xor (t1, s1, s2);
-      mark_set_for_renaming (t1);
-      BITMAP_FREE (t1);
-    }
+  VEC_safe_push (gimple_p, heap, scb_stack, stmt_p);
 }
 
-
-/* Pop the top SCB from SCB_STACK and act on the differences between
+/* Pop the top stmt from SCB_STACK and act on the differences between
    what was recorded by push_stmt_changes and the current state of
-   the statement.  */
+   the statement.  This function is deprecated, do not introduce
+   new uses of it.  */
 
 void
 pop_stmt_changes (gimple *stmt_p)
 {
-  tree op;
-  gimple stmt;
+  gimple *stmt2_p, stmt = *stmt_p;
   ssa_op_iter iter;
-  bitmap loads, stores;
-  scb_t buf;
-
-  stmt = *stmt_p;
+  tree op;
 
   /* It makes no sense to keep track of PHI nodes.  */
   if (gimple_code (stmt) == GIMPLE_PHI)
     return;
 
-  buf = VEC_pop (scb_t, scb_stack);
-  gcc_assert (stmt_p == buf->stmt_p);
+  stmt2_p = VEC_pop (gimple_p, scb_stack);
+  gcc_assert (stmt_p == stmt2_p);
 
   /* Force an operand re-scan on the statement and mark any newly
-     exposed variables.  */
+     exposed variables.  This also will mark the virtual operand
+     for renaming if necessary.  */
   update_stmt (stmt);
 
-  /* Determine whether any memory symbols need to be renamed.  If the
-     sets of loads and stores are different after the statement is
-     modified, then the affected symbols need to be renamed.
-     
-     Note that it may be possible for the statement to not reference
-     memory anymore, but we still need to act on the differences in
-     the sets of symbols.  */
-  loads = stores = NULL;
-  if (gimple_references_memory_p (stmt))
-    {
-      tree op;
-      ssa_op_iter i;
-
-      FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_VUSE)
-       {
-         tree sym = TREE_CODE (op) == SSA_NAME ? SSA_NAME_VAR (op) : op;
-         if (loads == NULL)
-           loads = BITMAP_ALLOC (NULL);
-         bitmap_set_bit (loads, DECL_UID (sym));
-       }
-
-      FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_VDEF)
-       {
-         tree sym = TREE_CODE (op) == SSA_NAME ? SSA_NAME_VAR (op) : op;
-         if (stores == NULL)
-           stores = BITMAP_ALLOC (NULL);
-         bitmap_set_bit (stores, DECL_UID (sym));
-       }
-    }
-
-  /* If LOADS is different from BUF->LOADS, the affected
-     symbols need to be marked for renaming.  */
-  mark_difference_for_renaming (loads, buf->loads);
-
-  /* Similarly for STORES and BUF->STORES.  */
-  mark_difference_for_renaming (stores, buf->stores);
-
-  /* Mark all the naked GIMPLE register operands for renaming.  */
+  /* Mark all the naked GIMPLE register operands for renaming.
+     ???  Especially this is considered bad behavior of the caller,
+     it should have updated SSA form manually.  Even more so as
+     we do not have a way to verify that no SSA names for op are
+     already in use.  */
   FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_DEF|SSA_OP_USE)
     if (DECL_P (op))
       mark_sym_for_renaming (op);
-
-  /* FIXME, need to add more finalizers here.  Cleanup EH info,
-     recompute invariants for address expressions, add
-     SSA replacement mappings, etc.  For instance, given
-     testsuite/gcc.c-torture/compile/pr16808.c, we fold a statement of
-     the form:
-
-         # SMT.4_20 = VDEF <SMT.4_16>
-         D.1576_11 = 1.0e+0;
-
-     So, the VDEF will disappear, but instead of marking SMT.4 for
-     renaming it would be far more efficient to establish a
-     replacement mapping that would replace every reference of
-     SMT.4_20 with SMT.4_16.  */
-
-  /* Free memory used by the buffer.  */
-  BITMAP_FREE (buf->loads);
-  BITMAP_FREE (buf->stores);
-  BITMAP_FREE (loads);
-  BITMAP_FREE (stores);
-  buf->stmt_p = NULL;
-  free (buf);
 }
 
-
-/* Discard the topmost change buffer from SCB_STACK.  This is useful
+/* Discard the topmost stmt from SCB_STACK.  This is useful
    when the caller realized that it did not actually modified the
-   statement.  It avoids the expensive operand re-scan.  */
+   statement.  It avoids the expensive operand re-scan.
+   This function is deprecated, do not introduce new uses of it.  */
 
 void
 discard_stmt_changes (gimple *stmt_p)
 {
-  scb_t buf;
-  gimple stmt;
+  gimple *stmt2_p, stmt = *stmt_p;
   
   /* It makes no sense to keep track of PHI nodes.  */
-  stmt = *stmt_p;
   if (gimple_code (stmt) == GIMPLE_PHI)
     return;
 
-  buf = VEC_pop (scb_t, scb_stack);
-  gcc_assert (stmt_p == buf->stmt_p);
+  stmt2_p = VEC_pop (gimple_p, scb_stack);
+  gcc_assert (stmt_p == stmt2_p);
+}
+
+/* Unlink STMTs virtual definition from the IL by propagating its use.  */
+
+void
+unlink_stmt_vdef (gimple stmt)
+{
+  use_operand_p use_p;
+  imm_use_iterator iter;
+  gimple use_stmt;
+  tree vdef = gimple_vdef (stmt);
+
+  if (!vdef
+      || TREE_CODE (vdef) != SSA_NAME)
+    return;
+
+  FOR_EACH_IMM_USE_STMT (use_stmt, iter, gimple_vdef (stmt))
+    {
+      FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
+       SET_USE (use_p, gimple_vuse (stmt));
+    }
 
-  /* Free memory used by the buffer.  */
-  BITMAP_FREE (buf->loads);
-  BITMAP_FREE (buf->stores);
-  buf->stmt_p = NULL;
-  free (buf);
+  if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_vdef (stmt)))
+    SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_vuse (stmt)) = 1;
 }
+
index bd30f82..a8d364d 100644 (file)
@@ -30,8 +30,8 @@ typedef tree *def_operand_p;
 typedef ssa_use_operand_t *use_operand_p;
 
 /* NULL operand types.  */
-#define NULL_USE_OPERAND_P             NULL
-#define NULL_DEF_OPERAND_P             NULL
+#define NULL_USE_OPERAND_P             ((use_operand_p)NULL)
+#define NULL_DEF_OPERAND_P             ((def_operand_p)NULL)
 
 /* This represents the DEF operands of a stmt.  */
 struct def_optype_d
@@ -49,63 +49,6 @@ struct use_optype_d
 };
 typedef struct use_optype_d *use_optype_p;
 
-typedef struct vuse_element_d
-{
-  tree use_var;
-  struct ssa_use_operand_d use_ptr;
-} vuse_element_t;
-
-typedef struct vuse_vec_d
-{
-  unsigned int num_vuse;
-  vuse_element_t uses[1];
-} vuse_vec_t;
-typedef struct vuse_vec_d *vuse_vec_p;
-
-#define VUSE_VECT_NUM_ELEM(V)          (V).num_vuse
-#define VUSE_VECT_ELEMENT_NC(V,X)      (V).uses[(X)]
-#define VUSE_ELEMENT_PTR_NC(V,X)       (&(VUSE_VECT_ELEMENT_NC ((V),(X)).use_ptr))
-#define VUSE_ELEMENT_VAR_NC(V,X)       (VUSE_VECT_ELEMENT_NC ((V),(X)).use_var)
-
-#ifdef ENABLE_CHECKING
-#define VUSE_VECT_ELEMENT(V,X)                                         \
-    (gcc_assert (((unsigned int) (X)) < VUSE_VECT_NUM_ELEM (V)),       \
-     VUSE_VECT_ELEMENT_NC (V,X))
-
-#define VUSE_ELEMENT_PTR(V,X)                                          \
-    (gcc_assert (((unsigned int) (X)) < VUSE_VECT_NUM_ELEM (V)),       \
-     VUSE_ELEMENT_PTR_NC (V, X))
-
-#define SET_VUSE_VECT_ELEMENT(V,X,N)                                   \
-    (gcc_assert (((unsigned int) (X)) < VUSE_VECT_NUM_ELEM (V)),       \
-     VUSE_VECT_ELEMENT_NC (V,X) = (N))
-
-#define SET_VUSE_ELEMENT_VAR(V,X,N)                                    \
-    (gcc_assert (((unsigned int) (X)) < VUSE_VECT_NUM_ELEM (V)),       \
-     VUSE_VECT_ELEMENT_NC ((V),(X)).use_var = (N))
-
-#define SET_VUSE_ELEMENT_PTR(V,X,N)                                    \
-    (gcc_assert (((unsigned int) (X)) < VUSE_VECT_NUM_ELEM (V)),       \
-     VUSE_ELEMENT_PTR_NC (V, X) = (N))
-#else
-#define VUSE_VECT_ELEMENT(V,X) VUSE_VECT_ELEMENT_NC(V,X)
-#define VUSE_ELEMENT_PTR(V,X) VUSE_ELEMENT_PTR_NC(V,X)
-#define SET_VUSE_VECT_ELEMENT(V,X,N) VUSE_VECT_ELEMENT_NC(V,X) = (N)
-#define SET_VUSE_ELEMENT_PTR(V,X,N) VUSE_ELEMENT_PTR_NC(V,X) = (N)
-#define SET_VUSE_ELEMENT_VAR(V,X,N) VUSE_VECT_ELEMENT_NC ((V),(X)).use_var = (N)
-#endif
-
-#define VUSE_ELEMENT_VAR(V,X)  (VUSE_VECT_ELEMENT ((V),(X)).use_var)
-
-/* This represents the virtual ops of a stmt.  */
-struct voptype_d
-{
-  struct voptype_d *next;
-  tree def_var;
-  vuse_vec_t usev;
-};
-typedef struct voptype_d *voptype_p;
-
 /* This structure represents a variable sized buffer which is allocated by the
    operand memory manager.  Operands are suballocated out of this block.  The
    MEM array varies in size.  */
@@ -116,9 +59,6 @@ struct ssa_operand_memory_d GTY((chain_next("%h.next")))
   char mem[1];
 };
 
-/* Number of different size free buckets for virtual operands.  */
-#define NUM_VOP_FREE_BUCKETS           29
-
 /* Per-function operand caches.  */
 struct ssa_operands GTY(()) {
    struct ssa_operand_memory_d *operand_memory;
@@ -130,28 +70,8 @@ struct ssa_operands GTY(()) {
 
    struct def_optype_d * GTY ((skip (""))) free_defs;
    struct use_optype_d * GTY ((skip (""))) free_uses;
-   struct voptype_d * GTY ((skip (""))) vop_free_buckets[NUM_VOP_FREE_BUCKETS];
-   VEC(tree,heap) * GTY ((skip (""))) mpt_table;
-};
-
-/* This represents the operand cache for a stmt.  */
-struct stmt_operands_d
-{
-  /* Statement operands.  */
-  struct def_optype_d * def_ops;
-  struct use_optype_d * use_ops;
-                                                                              
-  /* Virtual operands (VDEF, VUSE).  */
-  struct voptype_d * vdef_ops;
-  struct voptype_d * vuse_ops;
-
-  /* Sets of memory symbols loaded and stored.  */
-  bitmap stores;
-  bitmap loads;
 };
                                                                               
-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)
@@ -165,20 +85,6 @@ typedef struct stmt_operands_d *stmt_operands_p;
 #define DEF_OP_PTR(OP)         ((OP)->def_ptr)
 #define DEF_OP(OP)             (DEF_FROM_PTR (DEF_OP_PTR (OP)))
 
-#define VUSE_OP_PTR(OP,X)      VUSE_ELEMENT_PTR ((OP)->usev, (X)) 
-#define VUSE_OP(OP,X)          VUSE_ELEMENT_VAR ((OP)->usev, (X))
-#define SET_VUSE_OP(OP,X,N)    SET_VUSE_ELEMENT_VAR ((OP)->usev, (X), (N))
-#define VUSE_NUM(OP)           VUSE_VECT_NUM_ELEM ((OP)->usev)
-#define VUSE_VECT(OP)          &((OP)->usev)
-
-#define VDEF_RESULT_PTR(OP)    (&((OP)->def_var))
-#define VDEF_RESULT(OP)                ((OP)->def_var)
-#define VDEF_OP_PTR(OP,X)      VUSE_OP_PTR (OP, X)
-#define VDEF_OP(OP,X)          VUSE_OP (OP, X)
-#define SET_VDEF_OP(OP,X,N)    SET_VUSE_OP (OP, X, N)
-#define VDEF_NUM(OP)           VUSE_VECT_NUM_ELEM ((OP)->usev)
-#define VDEF_VECT(OP)          &((OP)->usev)
-
 #define PHI_RESULT_PTR(PHI)    gimple_phi_result_ptr (PHI)
 #define PHI_RESULT(PHI)                DEF_FROM_PTR (PHI_RESULT_PTR (PHI))
 #define SET_PHI_RESULT(PHI, V) SET_DEF (PHI_RESULT_PTR (PHI), (V))
@@ -200,10 +106,6 @@ extern void update_stmt_operands (gimple);
 extern void free_stmt_operands (gimple);
 extern bool verify_imm_links (FILE *f, tree var);
 
-extern void copy_virtual_operands (gimple, gimple);
-extern int operand_build_cmp (const void *, const void *);
-extern void create_ssa_artificial_load_stmt (gimple, gimple, bool);
-
 extern void dump_immediate_uses (FILE *file);
 extern void dump_immediate_uses_for (FILE *file, tree var);
 extern void debug_immediate_uses (void);
@@ -216,14 +118,14 @@ extern bool ssa_operands_active (void);
 extern void push_stmt_changes (gimple *);
 extern void pop_stmt_changes (gimple *);
 extern void discard_stmt_changes (gimple *);
-void add_to_addressable_set (tree, bitmap *);
+
+extern void unlink_stmt_vdef (gimple);
 
 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_vdef
+  ssa_op_iter_def
 };
 
 /* This structure is used in the operand iterator loops.  It contains the 
@@ -233,18 +135,13 @@ enum ssa_op_iter_type {
 
 typedef struct ssa_operand_iterator_d
 {
+  bool done;
+  enum ssa_op_iter_type iter_type;
   def_optype_p defs;
   use_optype_p uses;
-  voptype_p vuses;
-  voptype_p vdefs;
-  voptype_p mayuses;
-  enum ssa_op_iter_type iter_type;
   int phi_i;
   int num_phi;
   gimple phi_stmt;
-  bool done;
-  unsigned int vuse_index;
-  unsigned int mayuse_index;
 } ssa_op_iter;
 
 /* These flags are used to determine which operands are returned during 
@@ -252,11 +149,10 @@ typedef struct ssa_operand_iterator_d
 #define SSA_OP_USE             0x01    /* Real USE operands.  */
 #define SSA_OP_DEF             0x02    /* Real DEF operands.  */
 #define SSA_OP_VUSE            0x04    /* VUSE operands.  */
-#define SSA_OP_VMAYUSE         0x08    /* USE portion of VDEFS.  */
-#define SSA_OP_VDEF            0x10    /* DEF portion of VDEFS.  */
+#define SSA_OP_VDEF            0x08    /* VDEF operands.  */
 
 /* These are commonly grouped operand flags.  */
-#define SSA_OP_VIRTUAL_USES    (SSA_OP_VUSE | SSA_OP_VMAYUSE)
+#define SSA_OP_VIRTUAL_USES    (SSA_OP_VUSE)
 #define SSA_OP_VIRTUAL_DEFS    (SSA_OP_VDEF)
 #define SSA_OP_ALL_VIRTUALS     (SSA_OP_VIRTUAL_USES | SSA_OP_VIRTUAL_DEFS)
 #define SSA_OP_ALL_USES                (SSA_OP_VIRTUAL_USES | SSA_OP_USE)
@@ -287,14 +183,6 @@ typedef struct ssa_operand_iterator_d
        !op_iter_done (&(ITER));                                        \
        DEFVAR = op_iter_next_def (&(ITER)))
 
-/* This macro executes a loop over the VDEF operands of STMT.  The def
-   and use vector for each VDEF is returned in DEFVAR and USEVECT. 
-   ITER is an ssa_op_iter structure used to control the loop.  */
-#define FOR_EACH_SSA_VDEF_OPERAND(DEFVAR, USEVECT, STMT, ITER) \
-  for (op_iter_init_vdef (&(ITER), STMT, &(USEVECT), &(DEFVAR));       \
-       !op_iter_done (&(ITER));                                        \
-       op_iter_next_vdef (&(USEVECT), &(DEFVAR), &(ITER)))
-
 /* This macro will execute a loop over all the arguments of a PHI which
    match FLAGS.   A use_operand_p is always returned via USEVAR.  FLAGS
    can be either SSA_OP_USE or SSA_OP_VIRTUAL_USES or SSA_OP_ALL_USES.  */
index 27ad87d..d95b358 100644 (file)
@@ -105,12 +105,11 @@ static bool
 phivn_valid_p (struct phiprop_d *phivn, tree name, basic_block bb)
 {
   gimple vop_stmt = phivn[SSA_NAME_VERSION (name)].vop_stmt;
-  ssa_op_iter ui;
   tree vuse;
 
   /* The def stmts of all virtual uses need to be post-dominated
      by bb.  */
-  FOR_EACH_SSA_TREE_OPERAND (vuse, vop_stmt, ui, SSA_OP_VUSE)
+  if ((vuse = gimple_vuse (vop_stmt)))
     {
       gimple use_stmt;
       imm_use_iterator ui2;
@@ -120,7 +119,7 @@ phivn_valid_p (struct phiprop_d *phivn, tree name, basic_block bb)
        {
          /* If BB does not dominate a VDEF, the value is invalid.  */
          if (((is_gimple_assign (use_stmt)
-               && !ZERO_SSA_OPERANDS (use_stmt, SSA_OP_VDEF))
+               && gimple_vdef (use_stmt))
               || gimple_code (use_stmt) == GIMPLE_PHI)
              && !dominated_by_p (CDI_DOMINATORS, gimple_bb (use_stmt), bb))
            {
@@ -229,8 +228,7 @@ propagate_with_phi (basic_block bb, gimple phi, struct phiprop_d *phivn,
   ssa_op_iter i;
   bool phi_inserted;
 
-  if (MTAG_P (SSA_NAME_VAR (ptr))
-      || !POINTER_TYPE_P (TREE_TYPE (ptr))
+  if (!POINTER_TYPE_P (TREE_TYPE (ptr))
       || !is_gimple_reg_type (TREE_TYPE (TREE_TYPE (ptr))))
     return false;
 
@@ -271,7 +269,6 @@ propagate_with_phi (basic_block bb, gimple phi, struct phiprop_d *phivn,
   phi_inserted = false;
   FOR_EACH_IMM_USE_STMT (use_stmt, ui, ptr)
     {
-      ssa_op_iter ui2;
       tree vuse;
 
       /* Check whether this is a load of *ptr.  */
@@ -285,7 +282,7 @@ propagate_with_phi (basic_block bb, gimple phi, struct phiprop_d *phivn,
 
       /* Check if we can move the loads.  The def stmts of all virtual uses
         need to be post-dominated by bb.  */
-      FOR_EACH_SSA_TREE_OPERAND (vuse, use_stmt, ui2, SSA_OP_VUSE)
+      if ((vuse = gimple_vuse (use_stmt)) != NULL_TREE)
        {
          gimple def_stmt = SSA_NAME_DEF_STMT (vuse);
          if (!SSA_NAME_IS_DEFAULT_DEF (vuse)
index 267c2fc..c1cbe0c 100644 (file)
@@ -377,6 +377,9 @@ typedef struct bb_bitmap_sets
      the current iteration.  */
   bitmap_set_t new_sets;
 
+  /* A cache for value_dies_in_block_x.  */
+  bitmap expr_dies;
+
   /* True if we have visited this block during ANTIC calculation.  */
   unsigned int visited:1;
 
@@ -392,7 +395,8 @@ typedef struct bb_bitmap_sets
 #define ANTIC_IN(BB)   ((bb_value_sets_t) ((BB)->aux))->antic_in
 #define PA_IN(BB)      ((bb_value_sets_t) ((BB)->aux))->pa_in
 #define NEW_SETS(BB)   ((bb_value_sets_t) ((BB)->aux))->new_sets
-#define BB_VISITED(BB) ((bb_value_sets_t) ((BB)->aux))->visited
+#define EXPR_DIES(BB)  ((bb_value_sets_t) ((BB)->aux))->expr_dies
+#define BB_VISITED(BB) ((bb_value_sets_t) ((BB)->aux))->visited
 #define BB_DEFERRED(BB) ((bb_value_sets_t) ((BB)->aux))->deferred
 
 
@@ -906,26 +910,42 @@ print_pre_expr (FILE *outfile, const pre_expr expr)
             VEC_iterate (vn_reference_op_s, ref->operands, i, vro);
             i++)
          {
+           bool closebrace = false;
            if (vro->opcode != SSA_NAME
                && TREE_CODE_CLASS (vro->opcode) != tcc_declaration)
-             fprintf (outfile, "%s ", tree_code_name [vro->opcode]);
+             {
+               fprintf (outfile, "%s", tree_code_name [vro->opcode]);
+               if (vro->op0)
+                 {
+                   fprintf (outfile, "<");
+                   closebrace = true;
+                 }
+             }
            if (vro->op0)
              {
-               if (vro->op1)
-                 fprintf (outfile, "<");
                print_generic_expr (outfile, vro->op0, 0);
                if (vro->op1)
                  {
                    fprintf (outfile, ",");
                    print_generic_expr (outfile, vro->op1, 0);
                  }
-               if (vro->op1)
-                 fprintf (outfile, ">");
+               if (vro->op2)
+                 {
+                   fprintf (outfile, ",");
+                   print_generic_expr (outfile, vro->op2, 0);
+                 }
              }
+           if (closebrace)
+               fprintf (outfile, ">");
            if (i != VEC_length (vn_reference_op_s, ref->operands) - 1)
              fprintf (outfile, ",");
          }
        fprintf (outfile, "}");
+       if (ref->vuse)
+         {
+           fprintf (outfile, "@");
+           print_generic_expr (outfile, ref->vuse, 0);
+         }
       }
       break;
     }
@@ -1227,48 +1247,47 @@ do_unary:
   return e;
 }
 
-/* Translate the vuses in the VUSES vector backwards through phi nodes
-   in PHIBLOCK, so that they have the value they would have in
-   BLOCK. */
+/* Translate the VUSE backwards through phi nodes in PHIBLOCK, so that
+   it has the value it would have in BLOCK.  */
 
-static VEC(tree, gc) *
-translate_vuses_through_block (VEC (tree, gc) *vuses,
-                              basic_block phiblock,
-                              basic_block block)
+static tree
+translate_vuse_through_block (VEC (vn_reference_op_s, heap) *operands,
+                             tree vuse,
+                             basic_block phiblock,
+                             basic_block block)
 {
-  tree oldvuse;
-  VEC(tree, gc) *result = NULL;
-  int i;
+  gimple phi = SSA_NAME_DEF_STMT (vuse);
+  tree ref;
 
-  for (i = 0; VEC_iterate (tree, vuses, i, oldvuse); i++)
+  if (gimple_bb (phi) != phiblock)
+    return vuse;
+
+  if (gimple_code (phi) == GIMPLE_PHI)
     {
-      gimple phi = SSA_NAME_DEF_STMT (oldvuse);
-      if (gimple_code (phi) == GIMPLE_PHI
-         && gimple_bb (phi) == phiblock)
-       {
-         edge e = find_edge (block, gimple_bb (phi));
-         if (e)
-           {
-             tree def = PHI_ARG_DEF (phi, e->dest_idx);
-             if (def != oldvuse)
-               {
-                 if (!result)
-                   result = VEC_copy (tree, gc, vuses);
-                 VEC_replace (tree, result, i, def);
-               }
-           }
-       }
+      edge e = find_edge (block, phiblock);
+      return PHI_ARG_DEF (phi, e->dest_idx);
     }
 
-  /* We avoid creating a new copy of the vuses unless something
-     actually changed, so result can be NULL.  */
-  if (result)
+  if (!(ref = get_ref_from_reference_ops (operands)))
+    return NULL_TREE;
+
+  /* Use the alias-oracle to find either the PHI node in this block,
+     the first VUSE used in this block that is equivalent to vuse or
+     the first VUSE which definition in this block kills the value.  */
+  while (!stmt_may_clobber_ref_p (phi, ref))
     {
-      sort_vuses (result);
-      return result;
+      vuse = gimple_vuse (phi);
+      phi = SSA_NAME_DEF_STMT (vuse);
+      if (gimple_bb (phi) != phiblock)
+       return vuse;
+      if (gimple_code (phi) == GIMPLE_PHI)
+       {
+         edge e = find_edge (block, phiblock);
+         return PHI_ARG_DEF (phi, e->dest_idx);
+       }
     }
-  return vuses;
 
+  return NULL_TREE;
 }
 
 /* Like find_leader, but checks for the value existing in SET1 *or*
@@ -1540,8 +1559,8 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
       {
        vn_reference_t ref = PRE_EXPR_REFERENCE (expr);
        VEC (vn_reference_op_s, heap) *operands = ref->operands;
-       VEC (tree, gc) *vuses = ref->vuses;
-       VEC (tree, gc) *newvuses = vuses;
+       tree vuse = ref->vuse;
+       tree newvuse = vuse;
        VEC (vn_reference_op_s, heap) *newoperands = NULL;
        bool changed = false;
        unsigned int i;
@@ -1632,15 +1651,24 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
            return NULL;
          }
 
-       newvuses = translate_vuses_through_block (vuses, phiblock, pred);
-       changed |= newvuses != vuses;
+       if (vuse)
+         {
+           newvuse = translate_vuse_through_block (newoperands,
+                                                   vuse, phiblock, pred);
+           if (newvuse == NULL_TREE)
+             {
+               VEC_free (vn_reference_op_s, heap, newoperands);
+               return NULL;
+             }
+         }
+       changed |= newvuse != vuse;
 
        if (changed)
          {
            unsigned int new_val_id;
            pre_expr constant;
 
-           tree result = vn_reference_lookup_pieces (newvuses,
+           tree result = vn_reference_lookup_pieces (newvuse,
                                                      newoperands,
                                                      &newref, true);
            if (newref)
@@ -1671,7 +1699,7 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
                new_val_id = get_next_value_id ();
                VEC_safe_grow_cleared (bitmap_set_t, heap, value_expressions,
                                       get_max_value_id() + 1);
-               newref = vn_reference_insert_pieces (newvuses,
+               newref = vn_reference_insert_pieces (newvuse,
                                                     newoperands,
                                                     result, new_val_id);
                newoperands = NULL;
@@ -1846,24 +1874,73 @@ bitmap_find_leader (bitmap_set_t set, unsigned int val, gimple stmt)
 static bool
 value_dies_in_block_x (pre_expr expr, basic_block block)
 {
-  int i;
-  tree vuse;
-  VEC (tree, gc) *vuses = PRE_EXPR_REFERENCE (expr)->vuses;
+  tree vuse = PRE_EXPR_REFERENCE (expr)->vuse;
+  vn_reference_t refx = PRE_EXPR_REFERENCE (expr);
+  gimple def;
+  tree ref = NULL_TREE;
+  gimple_stmt_iterator gsi;
+  unsigned id = get_expression_id (expr);
+  bool res = false;
 
-  /* Conservatively, a value dies if it's vuses are defined in this
-     block, unless they come from phi nodes (which are merge operations,
-     rather than stores.  */
-  for (i = 0; VEC_iterate (tree, vuses, i, vuse); i++)
+  if (!vuse)
+    return false;
+
+  /* Lookup a previously calculated result.  */
+  if (EXPR_DIES (block)
+      && bitmap_bit_p (EXPR_DIES (block), id * 2))
+    return bitmap_bit_p (EXPR_DIES (block), id * 2 + 1);
+
+  /* A memory expression {e, VUSE} dies in the block if there is a
+     statement that may clobber e.  If, starting statement walk from the
+     top of the basic block, a statement uses VUSE there can be no kill
+     inbetween that use and the original statement that loaded {e, VUSE},
+     so we can stop walking.  */
+  for (gsi = gsi_start_bb (block); !gsi_end_p (gsi); gsi_next (&gsi))
     {
-      gimple def = SSA_NAME_DEF_STMT (vuse);
+      tree def_vuse, def_vdef;
+      def = gsi_stmt (gsi);
+      def_vuse = gimple_vuse (def);
+      def_vdef = gimple_vdef (def);
 
-      if (gimple_bb (def) != block)
+      /* Not a memory statement.  */
+      if (!def_vuse)
        continue;
-      if (gimple_code (def) == GIMPLE_PHI)
-       continue;
-      return true;
+
+      /* Not a may-def.  */
+      if (!def_vdef)
+       {
+         /* A load with the same VUSE, we're done.  */
+         if (def_vuse == vuse)
+           break;
+
+         continue;
+       }
+
+      /* Init ref only if we really need it.  */
+      if (ref == NULL_TREE)
+       {
+         if (!(ref = get_ref_from_reference_ops (refx->operands)))
+           {
+             res = true;
+             break;
+           }
+       }
+      /* If the statement may clobber expr, it dies.  */
+      if (stmt_may_clobber_ref_p (def, ref))
+       {
+         res = true;
+         break;
+       }
     }
-  return false;
+
+  /* Remember the result.  */
+  if (!EXPR_DIES (block))
+    EXPR_DIES (block) = BITMAP_ALLOC (&grand_bitmap_obstack);
+  bitmap_set_bit (EXPR_DIES (block), id * 2);
+  if (res)
+    bitmap_set_bit (EXPR_DIES (block), id * 2 + 1);
+
+  return res;
 }
 
 
@@ -1925,7 +2002,7 @@ vro_valid_in_sets (bitmap_set_t set1, bitmap_set_t set2,
    ONLY SET2 CAN BE NULL.
    This means that we have a leader for each part of the expression
    (if it consists of values), or the expression is an SSA_NAME.
-   For loads/calls, we also see if the vuses are killed in this block.
+   For loads/calls, we also see if the vuse is killed in this block.
 */
 
 static bool
@@ -1970,6 +2047,15 @@ valid_in_sets (bitmap_set_t set1, bitmap_set_t set2, pre_expr expr,
            if (!vro_valid_in_sets (set1, set2, vro))
              return false;
          }
+       if (ref->vuse)
+         {
+           gimple def_stmt = SSA_NAME_DEF_STMT (ref->vuse);
+           if (!gimple_nop_p (def_stmt)
+               && gimple_bb (def_stmt) != block
+               && !dominated_by_p (CDI_DOMINATORS,
+                                   block, gimple_bb (def_stmt)))
+             return false;
+         }
        return !value_dies_in_block_x (expr, block);
       }
     default:
@@ -3664,7 +3750,7 @@ compute_avail (void)
                  continue;
 
                copy_reference_ops_from_call (stmt, &ops);
-               vn_reference_lookup_pieces (shared_vuses_from_stmt (stmt),
+               vn_reference_lookup_pieces (gimple_vuse (stmt),
                                            ops, &ref, false);
                VEC_free (vn_reference_op_s, heap, ops);
                if (!ref)
@@ -3740,7 +3826,7 @@ compute_avail (void)
                      vn_reference_op_t vro;
 
                      vn_reference_lookup (gimple_assign_rhs1 (stmt),
-                                          shared_vuses_from_stmt (stmt),
+                                          gimple_vuse (stmt),
                                           false, &ref);
                      if (!ref)
                        continue;
@@ -3834,16 +3920,18 @@ do_SCCVN_insertion (gimple stmt, tree ssa_vn)
 static unsigned int
 eliminate (void)
 {
+  VEC (gimple, heap) *to_remove = NULL;
   basic_block b;
   unsigned int todo = 0;
+  gimple_stmt_iterator gsi;
+  gimple stmt;
+  unsigned i;
 
   FOR_EACH_BB (b)
     {
-      gimple_stmt_iterator i;
-
-      for (i = gsi_start_bb (b); !gsi_end_p (i);)
+      for (gsi = gsi_start_bb (b); !gsi_end_p (gsi); gsi_next (&gsi))
        {
-         gimple stmt = gsi_stmt (i);
+         stmt = gsi_stmt (gsi);
 
          /* Lookup the RHS of the expression, see if we have an
             available computation for it.  If so, replace the RHS with
@@ -3896,10 +3984,9 @@ eliminate (void)
                      print_gimple_stmt (dump_file, stmt, 0, 0);
                    }
                  pre_stats.eliminations++;
-                 propagate_tree_value_into_stmt (&i, sprime);
-                 stmt = gsi_stmt (i);
+                 propagate_tree_value_into_stmt (&gsi, sprime);
+                 stmt = gsi_stmt (gsi);
                  update_stmt (stmt);
-                 gsi_next (&i);
                  continue;
                }
 
@@ -3945,8 +4032,8 @@ eliminate (void)
                    sprime = fold_convert (gimple_expr_type (stmt), sprime);
 
                  pre_stats.eliminations++;
-                 propagate_tree_value_into_stmt (&i, sprime);
-                 stmt = gsi_stmt (i);
+                 propagate_tree_value_into_stmt (&gsi, sprime);
+                 stmt = gsi_stmt (gsi);
                  update_stmt (stmt);
 
                  /* If we removed EH side effects from the statement, clean
@@ -3971,45 +4058,20 @@ eliminate (void)
              tree rhs = gimple_assign_rhs1 (stmt);
              tree val;
              val = vn_reference_lookup (gimple_assign_lhs (stmt),
-                                        shared_vuses_from_stmt (stmt),
-                                        true, NULL);
+                                        gimple_vuse (stmt), true, NULL);
              if (TREE_CODE (rhs) == SSA_NAME)
                rhs = VN_INFO (rhs)->valnum;
              if (val
                  && operand_equal_p (val, rhs, 0))
                {
-                 def_operand_p def;
-                 use_operand_p use;
-                 vuse_vec_p usevec;
-                 ssa_op_iter oi;
-                 imm_use_iterator ui;
-                 gimple use_stmt;
-
                  if (dump_file && (dump_flags & TDF_DETAILS))
                    {
-                     fprintf (dump_file, "Deleted dead store ");
+                     fprintf (dump_file, "Deleted redundant store ");
                      print_gimple_stmt (dump_file, stmt, 0, 0);
                    }
 
-                 /* Propagate all may-uses to the uses of their defs.  */
-                 FOR_EACH_SSA_VDEF_OPERAND (def, usevec, stmt, oi)
-                   {
-                     tree vuse = VUSE_ELEMENT_VAR (*usevec, 0);
-                     tree vdef = DEF_FROM_PTR (def);
-
-                     /* If the vdef is used in an abnormal PHI node we
-                        have to propagate that flag to the vuse as well.  */
-                     if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (vdef))
-                       SSA_NAME_OCCURS_IN_ABNORMAL_PHI (vuse) = 1;
-
-                     FOR_EACH_IMM_USE_STMT (use_stmt, ui, vdef)
-                       FOR_EACH_IMM_USE_ON_STMT (use, ui)
-                         SET_USE (use, vuse);
-                   }
-
-                 gsi_remove (&i, true);
-                 release_defs (stmt);
-                 continue;
+                 /* Queue stmt for removal.  */
+                 VEC_safe_push (gimple, heap, to_remove, stmt);
                }
            }
          /* Visit COND_EXPRs and fold the comparison with the
@@ -4036,11 +4098,20 @@ eliminate (void)
                  todo = TODO_cleanup_cfg;
                }
            }
-
-         gsi_next (&i);
        }
     }
 
+  /* We cannot remove stmts during BB walk, especially not release SSA
+     names there as this confuses the VN machinery.  */
+  for (i = 0; VEC_iterate (gimple, to_remove, i, stmt); ++i)
+    {
+      gsi = gsi_for_stmt (stmt);
+      unlink_stmt_vdef (stmt);
+      gsi_remove (&gsi, true);
+      release_defs (stmt);
+    }
+  VEC_free (gimple, heap, to_remove);
+
   return todo;
 }
 
@@ -4341,7 +4412,7 @@ execute_pre (bool do_fre ATTRIBUTE_UNUSED)
 static unsigned int
 do_pre (void)
 {
-  return TODO_rebuild_alias | execute_pre (false);
+  return execute_pre (false);
 }
 
 static bool
@@ -4366,7 +4437,7 @@ struct gimple_opt_pass pass_pre =
     | PROP_ssa | PROP_alias,           /* properties_required */
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
-  0,                                   /* todo_flags_start */
+  TODO_rebuild_alias,                  /* todo_flags_start */
   TODO_update_ssa_only_virtuals | TODO_dump_func | TODO_ggc_collect
   | TODO_verify_ssa /* todo_flags_finish */
  }
index 4b338bc..ad68588 100644 (file)
@@ -730,8 +730,9 @@ update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
 
       new_stmt = gimple_build_call_vec (fn, args);
       gimple_call_set_lhs (new_stmt, lhs);
-      copy_virtual_operands (new_stmt, stmt);
       move_ssa_defining_stmt_for_defs (new_stmt, stmt);
+      gimple_set_vuse (new_stmt, gimple_vuse (stmt));
+      gimple_set_vdef (new_stmt, gimple_vdef (stmt));
       gimple_set_location (new_stmt, gimple_location (stmt));
       gsi_replace (si_p, new_stmt, false);
       VEC_free (tree, heap, args);
@@ -750,14 +751,17 @@ update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
              Introduce a new GIMPLE_ASSIGN statement.  */
           STRIP_USELESS_TYPE_CONVERSION (expr);
           new_stmt = gimple_build_assign (lhs, expr);
-          copy_virtual_operands (new_stmt, stmt);
           move_ssa_defining_stmt_for_defs (new_stmt, stmt);
+         gimple_set_vuse (new_stmt, gimple_vuse (stmt));
+         gimple_set_vdef (new_stmt, gimple_vdef (stmt));
         }
       else if (!TREE_SIDE_EFFECTS (expr))
         {
           /* No value is expected, and EXPR has no effect.
              Replace it with an empty statement.  */
           new_stmt = gimple_build_nop ();
+         unlink_stmt_vdef (stmt);
+         release_defs (stmt);
         }
       else
         {
@@ -771,7 +775,8 @@ update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
           add_referenced_var (lhs);
           lhs = make_ssa_name (lhs, new_stmt);
           gimple_assign_set_lhs (new_stmt, lhs);
-          copy_virtual_operands (new_stmt, stmt);
+         gimple_set_vuse (new_stmt, gimple_vuse (stmt));
+         gimple_set_vdef (new_stmt, gimple_vdef (stmt));
           move_ssa_defining_stmt_for_defs (new_stmt, stmt);
         }
       gimple_set_location (new_stmt, gimple_location (stmt));
@@ -842,7 +847,7 @@ stmt_makes_single_load (gimple stmt)
       != GIMPLE_SINGLE_RHS)
     return false;
 
-  if (ZERO_SSA_OPERANDS (stmt, SSA_OP_VDEF|SSA_OP_VUSE))
+  if (!gimple_vuse (stmt))
     return false;
 
   rhs = gimple_assign_rhs1 (stmt);
@@ -867,7 +872,7 @@ stmt_makes_single_store (gimple stmt)
       && gimple_code (stmt) != GIMPLE_CALL)
     return false;
 
-  if (ZERO_SSA_OPERANDS (stmt, SSA_OP_VDEF))
+  if (!gimple_vdef (stmt))
     return false;
 
   lhs = gimple_get_lhs (stmt);
index d28e1b6..a3e8468 100644 (file)
@@ -242,7 +242,7 @@ get_rank (tree e)
        return 0;
 
       if (!is_gimple_assign (stmt)
-         || !ZERO_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_DEFS))
+         || gimple_vdef (stmt))
        return bb_rank[gimple_bb (stmt)->index];
 
       /* If we already have a rank for this expression, use that.  */
index fb90392..8abc306 100644 (file)
@@ -426,13 +426,11 @@ vn_reference_hash (const void *p1)
 hashval_t
 vn_reference_compute_hash (const vn_reference_t vr1)
 {
-  hashval_t result = 0;
-  tree v;
+  hashval_t result;
   int i;
   vn_reference_op_t vro;
 
-  for (i = 0; VEC_iterate (tree, vr1->vuses, i, v); i++)
-    result += iterative_hash_expr (v, 0);
+  result = iterative_hash_expr (vr1->vuse, 0);
   for (i = 0; VEC_iterate (vn_reference_op_s, vr1->operands, i, vro); i++)
     result += vn_reference_op_compute_hash (vro);
 
@@ -445,7 +443,6 @@ vn_reference_compute_hash (const vn_reference_t vr1)
 int
 vn_reference_eq (const void *p1, const void *p2)
 {
-  tree v;
   int i;
   vn_reference_op_t vro;
 
@@ -454,15 +451,18 @@ vn_reference_eq (const void *p1, const void *p2)
   if (vr1->hashcode != vr2->hashcode)
     return false;
 
-  if (vr1->vuses == vr2->vuses
-      && vr1->operands == vr2->operands)
-    return true;
+  /* Early out if this is not a hash collision.  */
+  if (vr1->hashcode != vr2->hashcode)
+    return false;
 
-  /* Impossible for them to be equivalent if they have different
-     number of vuses.  */
-  if (VEC_length (tree, vr1->vuses) != VEC_length (tree, vr2->vuses))
+  /* The VOP needs to be the same.  */
+  if (vr1->vuse != vr2->vuse)
     return false;
 
+  /* If the operands are the same we are done.  */
+  if (vr1->operands == vr2->operands)
+    return true;
+
   /* We require that address operands be canonicalized in a way that
      two memory references will have the same operands if they are
      equivalent.  */
@@ -470,99 +470,12 @@ vn_reference_eq (const void *p1, const void *p2)
       != VEC_length (vn_reference_op_s, vr2->operands))
     return false;
 
-  /* The memory state is more often different than the address of the
-     store/load, so check it first.  */
-  for (i = 0; VEC_iterate (tree, vr1->vuses, i, v); i++)
-    {
-      if (VEC_index (tree, vr2->vuses, i) != v)
-       return false;
-    }
-
   for (i = 0; VEC_iterate (vn_reference_op_s, vr1->operands, i, vro); i++)
-    {
-      if (!vn_reference_op_eq (VEC_index (vn_reference_op_s, vr2->operands, i),
-                              vro))
-       return false;
-    }
-  return true;
-}
-
-/* Place the vuses from STMT into *result.  */
-
-static inline void
-vuses_to_vec (gimple stmt, VEC (tree, gc) **result)
-{
-  ssa_op_iter iter;
-  tree vuse;
-
-  if (!stmt)
-    return;
-
-  VEC_reserve_exact (tree, gc, *result,
-                    num_ssa_operands (stmt, SSA_OP_VIRTUAL_USES));
-
-  FOR_EACH_SSA_TREE_OPERAND (vuse, stmt, iter, SSA_OP_VIRTUAL_USES)
-    VEC_quick_push (tree, *result, vuse);
-}
-
-
-/* Copy the VUSE names in STMT into a vector, and return
-   the vector.  */
-
-static VEC (tree, gc) *
-copy_vuses_from_stmt (gimple stmt)
-{
-  VEC (tree, gc) *vuses = NULL;
-
-  vuses_to_vec (stmt, &vuses);
-
-  return vuses;
-}
-
-/* Place the vdefs from STMT into *result.  */
-
-static inline void
-vdefs_to_vec (gimple stmt, VEC (tree, gc) **result)
-{
-  ssa_op_iter iter;
-  tree vdef;
-
-  if (!stmt)
-    return;
-
-  *result = VEC_alloc (tree, gc, num_ssa_operands (stmt, SSA_OP_VIRTUAL_DEFS));
-
-  FOR_EACH_SSA_TREE_OPERAND (vdef, stmt, iter, SSA_OP_VIRTUAL_DEFS)
-    VEC_quick_push (tree, *result, vdef);
-}
-
-/* Copy the names of vdef results in STMT into a vector, and return
-   the vector.  */
-
-static VEC (tree, gc) *
-copy_vdefs_from_stmt (gimple stmt)
-{
-  VEC (tree, gc) *vdefs = NULL;
-
-  vdefs_to_vec (stmt, &vdefs);
-
-  return vdefs;
-}
-
-/* Place for shared_v{uses/defs}_from_stmt to shove vuses/vdefs.  */
-static VEC (tree, gc) *shared_lookup_vops;
-
-/* Copy the virtual uses from STMT into SHARED_LOOKUP_VOPS.
-   This function will overwrite the current SHARED_LOOKUP_VOPS
-   variable.  */
-
-VEC (tree, gc) *
-shared_vuses_from_stmt (gimple stmt)
-{
-  VEC_truncate (tree, shared_lookup_vops, 0);
-  vuses_to_vec (stmt, &shared_lookup_vops);
+    if (!vn_reference_op_eq (VEC_index (vn_reference_op_s, vr2->operands, i),
+                            vro))
+      return false;
 
-  return shared_lookup_vops;
+  return true;
 }
 
 /* Copy the operations present in load/store REF into RESULT, a vector of
@@ -696,7 +609,7 @@ copy_reference_ops_from_ref (tree ref, VEC(vn_reference_op_s, heap) **result)
    Returns NULL_TREE if the ops were not handled.
    This routine needs to be kept in sync with copy_reference_ops_from_ref.  */
 
-static tree
+tree
 get_ref_from_reference_ops (VEC(vn_reference_op_s, heap) *ops)
 {
   vn_reference_op_t op;
@@ -891,78 +804,6 @@ valueize_refs (VEC (vn_reference_op_s, heap) *orig)
   return orig;
 }
 
-/* Transform any SSA_NAME's in ORIG, a vector of vuse trees, into
-   their value numbers. This is done in-place, and the vector passed
-   in is returned.  */
-
-static VEC (tree, gc) *
-valueize_vuses (VEC (tree, gc) *orig)
-{
-  bool made_replacement = false;
-  tree vuse;
-  int i;
-
-  for (i = 0; VEC_iterate (tree, orig, i, vuse); i++)
-    {
-      if (vuse != SSA_VAL (vuse))
-       {
-         made_replacement = true;
-         VEC_replace (tree, orig, i, SSA_VAL (vuse));
-       }
-    }
-
-  if (made_replacement && VEC_length (tree, orig) > 1)
-    sort_vuses (orig);
-
-  return orig;
-}
-
-/* Return the single reference statement defining all virtual uses
-   in VUSES or NULL_TREE, if there are multiple defining statements.
-   Take into account only definitions that alias REF if following
-   back-edges.  */
-
-static gimple
-get_def_ref_stmt_vuses (tree ref, VEC (tree, gc) *vuses)
-{
-  gimple def_stmt;
-  tree vuse;
-  unsigned int i;
-
-  gcc_assert (VEC_length (tree, vuses) >= 1);
-
-  def_stmt = SSA_NAME_DEF_STMT (VEC_index (tree, vuses, 0));
-  if (gimple_code (def_stmt) == GIMPLE_PHI)
-    {
-      /* We can only handle lookups over PHI nodes for a single
-        virtual operand.  */
-      if (VEC_length (tree, vuses) == 1)
-       {
-         def_stmt = get_single_def_stmt_from_phi (ref, def_stmt);
-         goto cont;
-       }
-      else
-       return NULL;
-    }
-
-  /* Verify each VUSE reaches the same defining stmt.  */
-  for (i = 1; VEC_iterate (tree, vuses, i, vuse); ++i)
-    {
-      gimple tmp = SSA_NAME_DEF_STMT (vuse);
-      if (tmp != def_stmt)
-       return NULL;
-    }
-
-  /* Now see if the definition aliases ref, and loop until it does.  */
-cont:
-  while (def_stmt
-        && is_gimple_assign (def_stmt)
-        && !refs_may_alias_p (ref, gimple_get_lhs (def_stmt)))
-    def_stmt = get_single_def_stmt_with_phi (ref, def_stmt);
-
-  return def_stmt;
-}
-
 /* Lookup a SCCVN reference operation VR in the current hash table.
    Returns the resulting value number if it exists in the hash table,
    NULL_TREE otherwise.  VNRESULT will be filled in with the actual
@@ -990,6 +831,32 @@ vn_reference_lookup_1 (vn_reference_t vr, vn_reference_t *vnresult)
   return NULL_TREE;
 }
 
+/* Callback for walk_non_aliased_vuses.  Adjusts the vn_reference_t VR_
+   with the current VUSE and performs the expression lookup.  */
+
+static void *
+vn_reference_lookup_2 (tree op ATTRIBUTE_UNUSED, tree vuse, void *vr_)
+{
+  vn_reference_t vr = (vn_reference_t)vr_;
+  void **slot;
+  hashval_t hash;
+
+  /* Fixup vuse and hash.  */
+  vr->hashcode = vr->hashcode - iterative_hash_expr (vr->vuse, 0);
+  vr->vuse = SSA_VAL (vuse);
+  vr->hashcode = vr->hashcode + iterative_hash_expr (vr->vuse, 0);
+
+  hash = vr->hashcode;
+  slot = htab_find_slot_with_hash (current_info->references, vr,
+                                  hash, NO_INSERT);
+  if (!slot && current_info == optimistic_info)
+    slot = htab_find_slot_with_hash (valid_info->references, vr,
+                                    hash, NO_INSERT);
+  if (slot)
+    return *slot;
+  
+  return NULL;
+}
 
 /* Lookup a reference operation by it's parts, in the current hash table.
    Returns the resulting value number if it exists in the hash table,
@@ -997,43 +864,38 @@ vn_reference_lookup_1 (vn_reference_t vr, vn_reference_t *vnresult)
    vn_reference_t stored in the hashtable if something is found.  */
 
 tree
-vn_reference_lookup_pieces (VEC (tree, gc) *vuses,
+vn_reference_lookup_pieces (tree vuse,
                            VEC (vn_reference_op_s, heap) *operands,
                            vn_reference_t *vnresult, bool maywalk)
 {
   struct vn_reference_s vr1;
-  tree result;
-  if (vnresult)
-    *vnresult = NULL;
+  vn_reference_t tmp;
+
+  if (!vnresult)
+    vnresult = &tmp;
+  *vnresult = NULL;
   
-  vr1.vuses = valueize_vuses (vuses);
+  vr1.vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
   vr1.operands = valueize_refs (operands);
   vr1.hashcode = vn_reference_compute_hash (&vr1);
-  result = vn_reference_lookup_1 (&vr1, vnresult);
+  vn_reference_lookup_1 (&vr1, vnresult);
 
-  /* If there is a single defining statement for all virtual uses, we can
-     use that, following virtual use-def chains.  */
-  if (!result
+  if (!*vnresult
       && maywalk
-      && vr1.vuses
-      && VEC_length (tree, vr1.vuses) >= 1)
+      && vr1.vuse)
     {
       tree ref = get_ref_from_reference_ops (operands);
-      gimple def_stmt;
-      if (ref
-         && (def_stmt = get_def_ref_stmt_vuses (ref, vr1.vuses))
-         && is_gimple_assign (def_stmt))
-       {
-         /* We are now at an aliasing definition for the vuses we want to
-            look up.  Re-do the lookup with the vdefs for this stmt.  */
-         vdefs_to_vec (def_stmt, &vuses);
-         vr1.vuses = valueize_vuses (vuses);
-         vr1.hashcode = vn_reference_compute_hash (&vr1);
-         result = vn_reference_lookup_1 (&vr1, vnresult);
-       }
+      if (!ref)
+       return NULL_TREE;
+      *vnresult =
+       (vn_reference_t)walk_non_aliased_vuses (ref, vr1.vuse,
+                                               vn_reference_lookup_2, &vr1);
     }
 
-  return result;
+  if (*vnresult)
+     return (*vnresult)->result;
+
+  return NULL_TREE;
 }
 
 /* Lookup OP in the current hash table, and return the resulting value
@@ -1043,38 +905,36 @@ vn_reference_lookup_pieces (VEC (tree, gc) *vuses,
    stored in the hashtable if one exists.  */
 
 tree
-vn_reference_lookup (tree op, VEC (tree, gc) *vuses, bool maywalk,
+vn_reference_lookup (tree op, tree vuse, bool maywalk,
                     vn_reference_t *vnresult)
 {
   struct vn_reference_s vr1;
-  tree result;
-  gimple def_stmt;
+
   if (vnresult)
     *vnresult = NULL;
 
-  vr1.vuses = valueize_vuses (vuses);
+  vr1.vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
   vr1.operands = valueize_refs (shared_reference_ops_from_ref (op));
   vr1.hashcode = vn_reference_compute_hash (&vr1);
-  result = vn_reference_lookup_1 (&vr1, vnresult);
 
-  /* If there is a single defining statement for all virtual uses, we can
-     use that, following virtual use-def chains.  */
-  if (!result
-      && maywalk
-      && vr1.vuses
-      && VEC_length (tree, vr1.vuses) >= 1
-      && (def_stmt = get_def_ref_stmt_vuses (op, vr1.vuses))
-      && is_gimple_assign (def_stmt))
+  if (maywalk
+      && vr1.vuse)
     {
-      /* We are now at an aliasing definition for the vuses we want to
-        look up.  Re-do the lookup with the vdefs for this stmt.  */
-      vdefs_to_vec (def_stmt, &vuses);
-      vr1.vuses = valueize_vuses (vuses);
-      vr1.hashcode = vn_reference_compute_hash (&vr1);
-      result = vn_reference_lookup_1 (&vr1, vnresult);
+      vn_reference_t wvnresult;
+      wvnresult =
+       (vn_reference_t)walk_non_aliased_vuses (op, vr1.vuse,
+                                               vn_reference_lookup_2, &vr1);
+      if (wvnresult)
+       {
+         if (vnresult)
+           *vnresult = wvnresult;
+         return wvnresult->result;
+       }
+
+      return NULL_TREE;
     }
 
-  return result;
+  return vn_reference_lookup_1 (&vr1, vnresult);
 }
 
 
@@ -1082,7 +942,7 @@ vn_reference_lookup (tree op, VEC (tree, gc) *vuses, bool maywalk,
    RESULT, and return the resulting reference structure we created.  */
 
 vn_reference_t
-vn_reference_insert (tree op, tree result, VEC (tree, gc) *vuses)
+vn_reference_insert (tree op, tree result, tree vuse)
 {
   void **slot;
   vn_reference_t vr1;
@@ -1092,7 +952,7 @@ vn_reference_insert (tree op, tree result, VEC (tree, gc) *vuses)
     vr1->value_id = VN_INFO (result)->value_id;
   else
     vr1->value_id = get_or_alloc_constant_value_id (result);
-  vr1->vuses = valueize_vuses (vuses);
+  vr1->vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
   vr1->operands = valueize_refs (create_reference_ops_from_ref (op));
   vr1->hashcode = vn_reference_compute_hash (vr1);
   vr1->result = TREE_CODE (result) == SSA_NAME ? SSA_VAL (result) : result;
@@ -1121,7 +981,7 @@ vn_reference_insert (tree op, tree result, VEC (tree, gc) *vuses)
    structure we created.  */
 
 vn_reference_t
-vn_reference_insert_pieces (VEC (tree, gc) *vuses,
+vn_reference_insert_pieces (tree vuse,
                            VEC (vn_reference_op_s, heap) *operands,
                            tree result, unsigned int value_id)
 
@@ -1130,8 +990,8 @@ vn_reference_insert_pieces (VEC (tree, gc) *vuses,
   vn_reference_t vr1;
 
   vr1 = (vn_reference_t) pool_alloc (current_info->references_pool);
-  vr1->value_id =  value_id;
-  vr1->vuses = valueize_vuses (vuses);
+  vr1->value_id = value_id;
+  vr1->vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
   vr1->operands = valueize_refs (operands);
   vr1->hashcode = vn_reference_compute_hash (vr1);
   if (result && TREE_CODE (result) == SSA_NAME)
@@ -1142,8 +1002,8 @@ vn_reference_insert_pieces (VEC (tree, gc) *vuses,
                                   INSERT);
   
   /* At this point we should have all the things inserted that we have
-  seen before, and we should never try inserting something that
-  already exists.  */
+     seen before, and we should never try inserting something that
+     already exists.  */
   gcc_assert (!*slot);
   if (*slot)
     free_reference (*slot);
@@ -1614,7 +1474,7 @@ set_ssa_val_to (tree from, tree to)
 
   if (currval != to  && !operand_equal_p (currval, to, OEP_PURE_SAME))
     {
-      SSA_VAL (from) = to;
+      VN_INFO (from)->valnum = to;
       if (dump_file && (dump_flags & TDF_DETAILS))
        fprintf (dump_file, " (changed)\n");
       return true;
@@ -1722,8 +1582,9 @@ visit_reference_op_call (tree lhs, gimple stmt)
   bool changed = false;
   struct vn_reference_s vr1;
   tree result;
+  tree vuse = gimple_vuse (stmt);
 
-  vr1.vuses = valueize_vuses (shared_vuses_from_stmt (stmt));
+  vr1.vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
   vr1.operands = valueize_refs (shared_reference_ops_from_call (stmt));
   vr1.hashcode = vn_reference_compute_hash (&vr1);
   result = vn_reference_lookup_1 (&vr1, NULL);
@@ -1740,7 +1601,7 @@ visit_reference_op_call (tree lhs, gimple stmt)
       vn_reference_t vr2;
       changed = set_ssa_val_to (lhs, lhs);
       vr2 = (vn_reference_t) pool_alloc (current_info->references_pool);
-      vr2->vuses = valueize_vuses (copy_vuses_from_stmt (stmt));
+      vr2->vuse = vr1.vuse;
       vr2->operands = valueize_refs (create_reference_ops_from_call (stmt));
       vr2->hashcode = vr1.hashcode;
       vr2->result = lhs;
@@ -1761,8 +1622,7 @@ static bool
 visit_reference_op_load (tree lhs, tree op, gimple stmt)
 {
   bool changed = false;
-  tree result = vn_reference_lookup (op, shared_vuses_from_stmt (stmt), true,
-                                    NULL);
+  tree result = vn_reference_lookup (op, gimple_vuse (stmt), true, NULL);
 
   /* We handle type-punning through unions by value-numbering based
      on offset and size of the access.  Be prepared to handle a
@@ -1840,7 +1700,7 @@ visit_reference_op_load (tree lhs, tree op, gimple stmt)
   else
     {
       changed = set_ssa_val_to (lhs, lhs);
-      vn_reference_insert (op, lhs, copy_vuses_from_stmt (stmt));
+      vn_reference_insert (op, lhs, gimple_vuse (stmt));
     }
 
   return changed;
@@ -1873,8 +1733,7 @@ visit_reference_op_store (tree lhs, tree op, gimple stmt)
      Otherwise, the vdefs for the store are used when inserting into
      the table, since the store generates a new memory state.  */
 
-  result = vn_reference_lookup (lhs, shared_vuses_from_stmt (stmt), false,
-                               NULL);
+  result = vn_reference_lookup (lhs, gimple_vuse (stmt), false, NULL);
 
   if (result)
     {
@@ -1887,8 +1746,6 @@ visit_reference_op_store (tree lhs, tree op, gimple stmt)
 
   if (!result || !resultsame)
     {
-      VEC(tree, gc) *vdefs = copy_vdefs_from_stmt (stmt);
-      int i;
       tree vdef;
 
       if (dump_file && (dump_flags & TDF_DETAILS))
@@ -1902,7 +1759,7 @@ visit_reference_op_store (tree lhs, tree op, gimple stmt)
        }
       /* Have to set value numbers before insert, since insert is
         going to valueize the references in-place.  */
-      for (i = 0; VEC_iterate (tree, vdefs, i, vdef); i++)
+      if ((vdef = gimple_vdef (stmt)))
        {
          VN_INFO (vdef)->use_processed = true;
          changed |= set_ssa_val_to (vdef, vdef);
@@ -1911,36 +1768,23 @@ visit_reference_op_store (tree lhs, tree op, gimple stmt)
       /* Do not insert structure copies into the tables.  */
       if (is_gimple_min_invariant (op)
          || is_gimple_reg (op))
-        vn_reference_insert (lhs, op, vdefs);
+        vn_reference_insert (lhs, op, vdef);
     }
   else
     {
-      /* We had a match, so value number the vdefs to have the value
-        number of the vuses they came from.  */
-      ssa_op_iter op_iter;
-      def_operand_p var;
-      vuse_vec_p vv;
+      /* We had a match, so value number the vdef to have the value
+        number of the vuse it came from.  */
+      tree def, use;
 
       if (dump_file && (dump_flags & TDF_DETAILS))
        fprintf (dump_file, "Store matched earlier value,"
                 "value numbering store vdefs to matching vuses.\n");
 
-      FOR_EACH_SSA_VDEF_OPERAND (var, vv, stmt, op_iter)
-       {
-         tree def = DEF_FROM_PTR (var);
-         tree use;
-
-         /* Uh, if the vuse is a multiuse, we can't really do much
-            here, sadly, since we don't know which value number of
-            which vuse to use.  */
-         if (VUSE_VECT_NUM_ELEM (*vv) != 1)
-           use = def;
-         else
-           use = VUSE_ELEMENT_VAR (*vv, 0);
+      def = gimple_vdef (stmt);
+      use = gimple_vuse (stmt);
 
-         VN_INFO (def)->use_processed = true;
-         changed |= set_ssa_val_to (def, SSA_VAL (use));
-       }
+      VN_INFO (def)->use_processed = true;
+      changed |= set_ssa_val_to (def, SSA_VAL (use));
     }
 
   return changed;
@@ -2802,7 +2646,6 @@ init_scc_vn (void)
   gcc_obstack_init (&vn_ssa_aux_obstack);
 
   shared_lookup_phiargs = NULL;
-  shared_lookup_vops = NULL;
   shared_lookup_references = NULL;
   rpo_numbers = XCNEWVEC (int, last_basic_block + NUM_FIXED_BLOCKS);
   rpo_numbers_temp = XCNEWVEC (int, last_basic_block + NUM_FIXED_BLOCKS);
@@ -2848,7 +2691,6 @@ free_scc_vn (void)
   htab_delete (constant_to_value_id);
   BITMAP_FREE (constant_value_ids);
   VEC_free (tree, heap, shared_lookup_phiargs);
-  VEC_free (tree, gc, shared_lookup_vops);
   VEC_free (vn_reference_op_s, heap, shared_lookup_references);
   XDELETEVEC (rpo_numbers);
 
@@ -2941,7 +2783,7 @@ run_scc_vn (bool may_insert_arg)
       if (gimple_default_def (cfun, param) != NULL)
        {
          tree def = gimple_default_def (cfun, param);
-         SSA_VAL (def) = def;
+         VN_INFO (def)->valnum = def;
        }
     }
 
@@ -3074,32 +2916,6 @@ expressions_equal_p (tree e1, tree e2)
   return false;
 }
 
-/* Sort the VUSE array so that we can do equality comparisons
-   quicker on two vuse vecs.  */
-
-void
-sort_vuses (VEC (tree,gc) *vuses)
-{
-  if (VEC_length (tree, vuses) > 1)
-    qsort (VEC_address (tree, vuses),
-          VEC_length (tree, vuses),
-          sizeof (tree),
-          operand_build_cmp);
-}
-
-/* Sort the VUSE array so that we can do equality comparisons
-   quicker on two vuse vecs.  */
-
-void
-sort_vuses_heap (VEC (tree,heap) *vuses)
-{
-  if (VEC_length (tree, vuses) > 1)
-    qsort (VEC_address (tree, vuses),
-          VEC_length (tree, vuses),
-          sizeof (tree),
-          operand_build_cmp);
-}
-
 
 /* Return true if the nary operation NARY may trap.  This is a copy
    of stmt_could_throw_1_p adjusted to the SCCVN IL.  */
index bc6ecc0..644bc12 100644 (file)
@@ -79,20 +79,19 @@ typedef const vn_reference_op_s *const_vn_reference_op_t;
 DEF_VEC_O(vn_reference_op_s);
 DEF_VEC_ALLOC_O(vn_reference_op_s, heap);
 
-/* A reference operation in the hashtable is representation as a
-   collection of vuses, representing the memory state at the time of
+/* A reference operation in the hashtable is representation as
+   the vuse, representing the memory state at the time of
    the operation, and a collection of operands that make up the
    addressing calculation.  If two vn_reference_t's have the same set
    of operands, they access the same memory location. We also store
-   the resulting value number, and the hashcode.  The vuses are
-   always stored in order sorted by ssa name version.  */
+   the resulting value number, and the hashcode.  */
 
 typedef struct vn_reference_s
 {
   /* Unique identifier that all expressions with the same value have. */
   unsigned int value_id;
   hashval_t hashcode;
-  VEC (tree, gc) *vuses;
+  tree vuse;
   VEC (vn_reference_op_s, heap) *operands;
   tree result;
 } *vn_reference_t;
@@ -176,12 +175,13 @@ vn_nary_op_t vn_nary_op_insert_pieces (unsigned int, enum tree_code,
                                       tree, tree, unsigned int);
 void copy_reference_ops_from_ref (tree, VEC(vn_reference_op_s, heap) **);
 void copy_reference_ops_from_call (gimple, VEC(vn_reference_op_s, heap) **);
-tree vn_reference_lookup_pieces (VEC (tree, gc) *,
+tree get_ref_from_reference_ops (VEC(vn_reference_op_s, heap) *ops);
+tree vn_reference_lookup_pieces (tree,
                                 VEC (vn_reference_op_s, heap) *,
                                 vn_reference_t *, bool);
-tree vn_reference_lookup (tree, VEC (tree, gc) *, bool, vn_reference_t *);
-vn_reference_t vn_reference_insert (tree, tree, VEC (tree, gc) *);
-vn_reference_t vn_reference_insert_pieces (VEC (tree, gc) *,
+tree vn_reference_lookup (tree, tree, bool, vn_reference_t *);
+vn_reference_t vn_reference_insert (tree, tree, tree);
+vn_reference_t vn_reference_insert_pieces (tree,
                                           VEC (vn_reference_op_s, heap) *,
                                           tree, unsigned int);
 
@@ -195,5 +195,4 @@ unsigned int get_next_value_id (void);
 unsigned int get_constant_value_id (tree);
 unsigned int get_or_alloc_constant_value_id (tree);
 bool value_id_constant_p (unsigned int);
-VEC (tree, gc) *shared_vuses_from_stmt (gimple);
 #endif /* TREE_SSA_SCCVN_H  */
index a190a22..d0c550d 100644 (file)
@@ -140,7 +140,7 @@ is_hidden_global_store (gimple stmt)
   /* Check virtual definitions.  If we get here, the only virtual
      definitions we should see are those generated by assignment or call
      statements.  */
-  if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_DEFS))
+  if (gimple_vdef (stmt))
     {
       tree lhs;
 
@@ -191,7 +191,7 @@ is_hidden_global_store (gimple stmt)
 
        }
       else if (INDIRECT_REF_P (lhs))
-       return may_point_to_global_var (TREE_OPERAND (lhs, 0));
+       return ptr_deref_may_alias_global_p (TREE_OPERAND (lhs, 0));
       else
        gcc_unreachable ();
     }
@@ -317,7 +317,7 @@ statement_sink_location (gimple stmt, basic_block frombb,
       || code == FILTER_EXPR
       || is_hidden_global_store (stmt)
       || gimple_has_volatile_ops (stmt)
-      || !ZERO_SSA_OPERANDS (stmt, SSA_OP_VUSE)
+      || gimple_vuse (stmt)
       || (cfun->has_local_explicit_reg_vars
          && TYPE_MODE (TREE_TYPE (gimple_assign_lhs (stmt))) == BLKmode))
     return false;
index 1cb07f5..7ac27c0 100644 (file)
@@ -48,7 +48,6 @@
 #include "alloc-pool.h"
 #include "splay-tree.h"
 #include "params.h"
-#include "tree-ssa-structalias.h"
 #include "cgraph.h"
 #include "alias.h"
 #include "pointer-set.h"
@@ -185,6 +184,9 @@ static unsigned int create_variable_info_for (tree, const char *);
 typedef struct constraint_graph *constraint_graph_t;
 static void unify_nodes (constraint_graph_t, unsigned int, unsigned int, bool);
 
+struct constraint;
+typedef struct constraint *constraint_t;
+
 DEF_VEC_P(constraint_t);
 DEF_VEC_ALLOC_P(constraint_t,heap);
 
@@ -233,11 +235,6 @@ struct variable_info
   /* True if this field may contain pointers.  */
   unsigned int may_have_pointers : 1;
 
-  /* Variable id this was collapsed to due to type unsafety.  Zero if
-     this variable was not collapsed.  This should be unused completely
-     after build_succ_graph, or something is broken.  */
-  unsigned int collapsed_to;
-
   /* A link to the variable for the next field in this structure.  */
   struct variable_info *next;
 
@@ -265,6 +262,8 @@ struct variable_info
 typedef struct variable_info *varinfo_t;
 
 static varinfo_t first_vi_for_offset (varinfo_t, unsigned HOST_WIDE_INT);
+static varinfo_t first_or_preceding_vi_for_offset (varinfo_t,
+                                                  unsigned HOST_WIDE_INT);
 static varinfo_t lookup_vi_for_tree (tree);
 
 /* Pool of variable info structures.  */
@@ -286,18 +285,6 @@ get_varinfo (unsigned int n)
   return VEC_index (varinfo_t, varmap, n);
 }
 
-/* Return the varmap element N, following the collapsed_to link.  */
-
-static inline varinfo_t
-get_varinfo_fc (unsigned int n)
-{
-  varinfo_t v = VEC_index (varinfo_t, varmap, n);
-
-  if (v->collapsed_to != 0)
-    return get_varinfo (v->collapsed_to);
-  return v;
-}
-
 /* Static IDs for the special variables.  */
 enum { nothing_id = 0, anything_id = 1, readonly_id = 2,
        escaped_id = 3, nonlocal_id = 4, callused_id = 5,
@@ -395,7 +382,6 @@ new_var_info (tree t, unsigned int id, const char *name)
   ret->solution = BITMAP_ALLOC (&pta_obstack);
   ret->oldsolution = BITMAP_ALLOC (&oldpta_obstack);
   ret->next = NULL;
-  ret->collapsed_to = 0;
   return ret;
 }
 
@@ -416,9 +402,12 @@ struct constraint_expr
 
      IOW, in a deref constraint, we would deref, get the result set,
      then add OFFSET to each member.   */
-  unsigned HOST_WIDE_INT offset;
+  HOST_WIDE_INT offset;
 };
 
+/* Use 0x8000... as special unknown offset.  */
+#define UNKNOWN_OFFSET ((HOST_WIDE_INT)-1 << (HOST_BITS_PER_WIDE_INT-1))
+
 typedef struct constraint_expr ce_s;
 DEF_VEC_O(ce_s);
 DEF_VEC_ALLOC_O(ce_s, heap);
@@ -575,27 +564,38 @@ new_constraint (const struct constraint_expr lhs,
 
 /* Print out constraint C to FILE.  */
 
-void
+static void
 dump_constraint (FILE *file, constraint_t c)
 {
   if (c->lhs.type == ADDRESSOF)
     fprintf (file, "&");
   else if (c->lhs.type == DEREF)
     fprintf (file, "*");
-  fprintf (file, "%s", get_varinfo_fc (c->lhs.var)->name);
-  if (c->lhs.offset != 0)
+  fprintf (file, "%s", get_varinfo (c->lhs.var)->name);
+  if (c->lhs.offset == UNKNOWN_OFFSET)
+    fprintf (file, " + UNKNOWN");
+  else if (c->lhs.offset != 0)
     fprintf (file, " + " HOST_WIDE_INT_PRINT_DEC, c->lhs.offset);
   fprintf (file, " = ");
   if (c->rhs.type == ADDRESSOF)
     fprintf (file, "&");
   else if (c->rhs.type == DEREF)
     fprintf (file, "*");
-  fprintf (file, "%s", get_varinfo_fc (c->rhs.var)->name);
-  if (c->rhs.offset != 0)
+  fprintf (file, "%s", get_varinfo (c->rhs.var)->name);
+  if (c->rhs.offset == UNKNOWN_OFFSET)
+    fprintf (file, " + UNKNOWN");
+  else if (c->rhs.offset != 0)
     fprintf (file, " + " HOST_WIDE_INT_PRINT_DEC, c->rhs.offset);
   fprintf (file, "\n");
 }
 
+
+void debug_constraint (constraint_t);
+void debug_constraints (void);
+void debug_constraint_graph (void);
+void debug_solution_for_var (unsigned int);
+void debug_sa_points_to_info (void);
+
 /* Print out constraint C to stderr.  */
 
 void
@@ -606,7 +606,7 @@ debug_constraint (constraint_t c)
 
 /* Print out all constraints to FILE */
 
-void
+static void
 dump_constraints (FILE *file)
 {
   int i;
@@ -630,13 +630,13 @@ debug_constraints (void)
    complex with an offset, e.g: a = b + 8, then the label is "+".
    Otherwise the edge has no label.  */
 
-void
+static void
 dump_constraint_edge (FILE *file, constraint_t c)
 {
   if (c->rhs.type != ADDRESSOF)
     {
-      const char *src = get_varinfo_fc (c->rhs.var)->name;
-      const char *dst = get_varinfo_fc (c->lhs.var)->name;
+      const char *src = get_varinfo (c->rhs.var)->name;
+      const char *dst = get_varinfo (c->lhs.var)->name;
       fprintf (file, "  \"%s\" -> \"%s\" ", src, dst);
       /* Due to preprocessing of constraints, instructions like *a = *b are
          illegal; thus, we do not have to handle such cases.  */
@@ -658,7 +658,7 @@ dump_constraint_edge (FILE *file, constraint_t c)
 
 /* Print the constraint graph in dot format.  */
 
-void
+static void
 dump_constraint_graph (FILE *file)
 {
   unsigned int i=0, size;
@@ -690,7 +690,7 @@ dump_constraint_graph (FILE *file)
   size = size < graph->size ? size : graph->size;
   for (i = 0; i < size; i++)
     {
-      const char *name = get_varinfo_fc (graph->rep[i])->name;
+      const char *name = get_varinfo (graph->rep[i])->name;
       fprintf (file, "  \"%s\" ;\n", name);
     }
 
@@ -833,16 +833,62 @@ constraint_set_union (VEC(constraint_t,heap) **to,
     }
 }
 
+/* Expands the solution in SET to all sub-fields of variables included.
+   Union the expanded result into RESULT.  */
+
+static void
+solution_set_expand (bitmap result, bitmap set)
+{
+  bitmap_iterator bi;
+  bitmap vars = NULL;
+  unsigned j;
+
+  /* In a first pass record all variables we need to add all
+     sub-fields off.  This avoids quadratic behavior.  */
+  EXECUTE_IF_SET_IN_BITMAP (set, 0, j, bi)
+    {
+      varinfo_t v = get_varinfo (j);
+      if (v->is_artificial_var
+         || v->is_full_var)
+       continue;
+      v = lookup_vi_for_tree (v->decl);
+      if (vars == NULL)
+       vars = BITMAP_ALLOC (NULL);
+      bitmap_set_bit (vars, v->id);
+    }
+
+  /* In the second pass now do the addition to the solution and
+     to speed up solving add it to the delta as well.  */
+  if (vars != NULL)
+    {
+      EXECUTE_IF_SET_IN_BITMAP (vars, 0, j, bi)
+       {
+         varinfo_t v = get_varinfo (j);
+         for (; v != NULL; v = v->next)
+           bitmap_set_bit (result, v->id);
+       }
+      BITMAP_FREE (vars);
+    }
+}
+
 /* Take a solution set SET, add OFFSET to each member of the set, and
    overwrite SET with the result when done.  */
 
 static void
-solution_set_add (bitmap set, unsigned HOST_WIDE_INT offset)
+solution_set_add (bitmap set, HOST_WIDE_INT offset)
 {
   bitmap result = BITMAP_ALLOC (&iteration_obstack);
   unsigned int i;
   bitmap_iterator bi;
 
+  /* If the offset is unknown we have to expand the solution to
+     all subfields.  */
+  if (offset == UNKNOWN_OFFSET)
+    {
+      solution_set_expand (set, set);
+      return;
+    }
+
   EXECUTE_IF_SET_IN_BITMAP (set, 0, i, bi)
     {
       varinfo_t vi = get_varinfo (i);
@@ -856,21 +902,23 @@ solution_set_add (bitmap set, unsigned HOST_WIDE_INT offset)
       else
        {
          unsigned HOST_WIDE_INT fieldoffset = vi->offset + offset;
-         varinfo_t v = first_vi_for_offset (vi, fieldoffset);
-         /* If the result is outside of the variable use the last field.  */
-         if (!v)
-           {
-             v = vi;
-             while (v->next != NULL)
-               v = v->next;
-           }
-         bitmap_set_bit (result, v->id);
+
+         /* If the offset makes the pointer point to before the
+            variable use offset zero for the field lookup.  */
+         if (offset < 0
+             && fieldoffset > vi->offset)
+           fieldoffset = 0;
+
+         if (offset != 0)
+           vi = first_or_preceding_vi_for_offset (vi, fieldoffset);
+
+         bitmap_set_bit (result, vi->id);
          /* If the result is not exactly at fieldoffset include the next
             field as well.  See get_constraint_for_ptr_offset for more
             rationale.  */
-         if (v->offset != fieldoffset
-             && v->next != NULL)
-           bitmap_set_bit (result, v->next->id);
+         if (vi->offset != fieldoffset
+             && vi->next != NULL)
+           bitmap_set_bit (result, vi->next->id);
        }
     }
 
@@ -882,7 +930,7 @@ solution_set_add (bitmap set, unsigned HOST_WIDE_INT offset)
    process.  */
 
 static bool
-set_union_with_increment  (bitmap to, bitmap from, unsigned HOST_WIDE_INT inc)
+set_union_with_increment  (bitmap to, bitmap from, HOST_WIDE_INT inc)
 {
   if (inc == 0)
     return bitmap_ior_into (to, from);
@@ -1119,8 +1167,8 @@ build_pred_graph (void)
     {
       struct constraint_expr lhs = c->lhs;
       struct constraint_expr rhs = c->rhs;
-      unsigned int lhsvar = get_varinfo_fc (lhs.var)->id;
-      unsigned int rhsvar = get_varinfo_fc (rhs.var)->id;
+      unsigned int lhsvar = lhs.var;
+      unsigned int rhsvar = rhs.var;
 
       if (lhs.type == DEREF)
        {
@@ -1154,17 +1202,17 @@ build_pred_graph (void)
 
          /* All related variables are no longer direct nodes.  */
          RESET_BIT (graph->direct_nodes, rhsvar);
-         v = get_varinfo (rhsvar);
-         if (!v->is_full_var)
-           {
-             v = lookup_vi_for_tree (v->decl);
-             do
-               {
-                 RESET_BIT (graph->direct_nodes, v->id);
-                 v = v->next;
-               }
-             while (v != NULL);
-           }
+          v = get_varinfo (rhsvar);
+          if (!v->is_full_var)
+            {
+              v = lookup_vi_for_tree (v->decl);
+              do
+                {
+                  RESET_BIT (graph->direct_nodes, v->id);
+                  v = v->next;
+                }
+              while (v != NULL);
+            }
          bitmap_set_bit (graph->address_taken, rhsvar);
        }
       else if (lhsvar > anything_id
@@ -1206,8 +1254,8 @@ build_succ_graph (void)
 
       lhs = c->lhs;
       rhs = c->rhs;
-      lhsvar = find (get_varinfo_fc (lhs.var)->id);
-      rhsvar = find (get_varinfo_fc (rhs.var)->id);
+      lhsvar = find (lhs.var);
+      rhsvar = find (rhs.var);
 
       if (lhs.type == DEREF)
        {
@@ -1222,8 +1270,7 @@ build_succ_graph (void)
       else if (rhs.type == ADDRESSOF)
        {
          /* x = &y */
-         gcc_assert (find (get_varinfo_fc (rhs.var)->id)
-                     == get_varinfo_fc (rhs.var)->id);
+         gcc_assert (find (rhs.var) == rhs.var);
          bitmap_set_bit (get_varinfo (lhsvar)->solution, rhsvar);
        }
       else if (lhsvar > anything_id
@@ -1485,29 +1532,8 @@ topo_visit (constraint_graph_t graph, struct topo_info *ti,
   VEC_safe_push (unsigned, heap, ti->topo_order, n);
 }
 
-/* Return true if variable N + OFFSET is a legal field of N.  */
-
-static bool
-type_safe (unsigned int n, unsigned HOST_WIDE_INT *offset)
-{
-  varinfo_t ninfo = get_varinfo (n);
-
-  /* For things we've globbed to single variables, any offset into the
-     variable acts like the entire variable, so that it becomes offset
-     0.  */
-  if (ninfo->is_special_var
-      || ninfo->is_artificial_var
-      || ninfo->is_unknown_size_var
-      || ninfo->is_full_var)
-    {
-      *offset = 0;
-      return true;
-    }
-  return (get_varinfo (n)->offset + *offset) < get_varinfo (n)->fullsize;
-}
-
-/* Process a constraint C that represents x = *y, using DELTA as the
-   starting solution.  */
+/* Process a constraint C that represents x = *(y + off), using DELTA as the
+   starting solution for y.  */
 
 static void
 do_sd_constraint (constraint_graph_t graph, constraint_t c,
@@ -1518,73 +1544,47 @@ do_sd_constraint (constraint_graph_t graph, constraint_t c,
   bitmap sol = get_varinfo (lhs)->solution;
   unsigned int j;
   bitmap_iterator bi;
+  HOST_WIDE_INT roffset = c->rhs.offset;
 
-  /* For x = *ESCAPED and x = *CALLUSED we want to compute the
-     reachability set of the rhs var.  As a pointer to a sub-field
-     of a variable can also reach all other fields of the variable
-     we simply have to expand the solution to contain all sub-fields
-     if one sub-field is contained.  */
-  if (c->rhs.var == find (escaped_id)
-      || c->rhs.var == find (callused_id))
-    {
-      bitmap vars = NULL;
-      /* In a first pass record all variables we need to add all
-         sub-fields off.  This avoids quadratic behavior.  */
-      EXECUTE_IF_SET_IN_BITMAP (delta, 0, j, bi)
-       {
-         varinfo_t v = get_varinfo (j);
-         if (v->is_full_var)
-           continue;
-
-         v = lookup_vi_for_tree (v->decl);
-         if (v->next != NULL)
-           {
-             if (vars == NULL)
-               vars = BITMAP_ALLOC (NULL);
-             bitmap_set_bit (vars, v->id);
-           }
-       }
-      /* In the second pass now do the addition to the solution and
-         to speed up solving add it to the delta as well.  */
-      if (vars != NULL)
-       {
-         EXECUTE_IF_SET_IN_BITMAP (vars, 0, j, bi)
-           {
-             varinfo_t v = get_varinfo (j);
-             for (; v != NULL; v = v->next)
-               {
-                 if (bitmap_set_bit (sol, v->id))
-                   {
-                     flag = true;
-                     bitmap_set_bit (delta, v->id);
-                   }
-               }
-           }
-         BITMAP_FREE (vars);
-       }
-    }
+  /* Our IL does not allow this.  */
+  gcc_assert (c->lhs.offset == 0);
 
+  /* If the solution of Y contains anything it is good enough to transfer
+     this to the LHS.  */
   if (bitmap_bit_p (delta, anything_id))
     {
       flag |= bitmap_set_bit (sol, anything_id);
       goto done;
     }
 
+  /* If we do not know at with offset the rhs is dereferenced compute
+     the reachability set of DELTA, conservatively assuming it is
+     dereferenced at all valid offsets.  */
+  if (roffset == UNKNOWN_OFFSET)
+    {
+      solution_set_expand (delta, delta);
+      /* No further offset processing is necessary.  */
+      roffset = 0;
+    }
+
   /* For each variable j in delta (Sol(y)), add
      an edge in the graph from j to x, and union Sol(j) into Sol(x).  */
   EXECUTE_IF_SET_IN_BITMAP (delta, 0, j, bi)
     {
-      unsigned HOST_WIDE_INT roffset = c->rhs.offset;
-      if (type_safe (j, &roffset))
-       {
-         varinfo_t v;
-         unsigned HOST_WIDE_INT fieldoffset = get_varinfo (j)->offset + roffset;
-         unsigned int t;
+      varinfo_t v = get_varinfo (j);
+      HOST_WIDE_INT fieldoffset = v->offset + roffset;
+      unsigned int t;
+
+      if (v->is_full_var)
+       fieldoffset = v->offset;
+      else if (roffset != 0)
+       v = first_vi_for_offset (v, fieldoffset);
+      /* If the access is outside of the variable we can ignore it.  */
+      if (!v)
+       continue;
 
-         v = first_vi_for_offset (get_varinfo (j), fieldoffset);
-         /* If the access is outside of the variable we can ignore it.  */
-         if (!v)
-           continue;
+      do
+       {
          t = find (v->id);
 
          /* Adding edges from the special vars is pointless.
@@ -1593,11 +1593,21 @@ do_sd_constraint (constraint_graph_t graph, constraint_t c,
            flag |= bitmap_ior_into (sol, get_varinfo (t)->solution);
          /* Merging the solution from ESCAPED needlessly increases
             the set.  Use ESCAPED as representative instead.  */
-         else if (get_varinfo (t)->id == find (escaped_id))
+         else if (v->id == escaped_id)
            flag |= bitmap_set_bit (sol, escaped_id);
          else if (add_graph_edge (graph, lhs, t))
            flag |= bitmap_ior_into (sol, get_varinfo (t)->solution);
+
+         /* If the variable is not exactly at the requested offset
+            we have to include the next one.  */
+         if (v->offset == (unsigned HOST_WIDE_INT)fieldoffset
+             || v->next == NULL)
+           break;
+
+         v = v->next;
+         fieldoffset = v->offset;
        }
+      while (1);
     }
 
 done:
@@ -1613,7 +1623,8 @@ done:
     }
 }
 
-/* Process a constraint C that represents *x = y.  */
+/* Process a constraint C that represents *(x + off) = y using DELTA
+   as the starting solution for x.  */
 
 static void
 do_ds_constraint (constraint_t c, bitmap delta)
@@ -1622,6 +1633,7 @@ do_ds_constraint (constraint_t c, bitmap delta)
   bitmap sol = get_varinfo (rhs)->solution;
   unsigned int j;
   bitmap_iterator bi;
+  HOST_WIDE_INT loff = c->lhs.offset;
 
   /* Our IL does not allow this.  */
   gcc_assert (c->rhs.offset == 0);
@@ -1651,22 +1663,36 @@ do_ds_constraint (constraint_t c, bitmap delta)
       return;
     }
 
+  /* If we do not know at with offset the rhs is dereferenced compute
+     the reachability set of DELTA, conservatively assuming it is
+     dereferenced at all valid offsets.  */
+  if (loff == UNKNOWN_OFFSET)
+    {
+      solution_set_expand (delta, delta);
+      loff = 0;
+    }
+
   /* For each member j of delta (Sol(x)), add an edge from y to j and
      union Sol(y) into Sol(j) */
   EXECUTE_IF_SET_IN_BITMAP (delta, 0, j, bi)
     {
-      unsigned HOST_WIDE_INT loff = c->lhs.offset;
-      if (type_safe (j, &loff) && !(get_varinfo (j)->is_special_var))
-       {
-         varinfo_t v;
-         unsigned int t;
-         unsigned HOST_WIDE_INT fieldoffset = get_varinfo (j)->offset + loff;
+      varinfo_t v = get_varinfo (j);
+      unsigned int t;
+      HOST_WIDE_INT fieldoffset = v->offset + loff;
 
-         v = first_vi_for_offset (get_varinfo (j), fieldoffset);
-         /* If the access is outside of the variable we can ignore it.  */
-         if (!v)
-           continue;
+      if (v->is_special_var)
+       continue;
+
+      if (v->is_full_var)
+       fieldoffset = v->offset;
+      else if (loff != 0)
+       v = first_vi_for_offset (v, fieldoffset);
+      /* If the access is outside of the variable we can ignore it.  */
+      if (!v)
+       continue;
 
+      do
+       {
          if (v->may_have_pointers)
            {
              t = find (v->id);
@@ -1684,7 +1710,17 @@ do_ds_constraint (constraint_t c, bitmap delta)
                    }
                }
            }
+
+         /* If the variable is not exactly at the requested offset
+            we have to include the next one.  */
+         if (v->offset == (unsigned HOST_WIDE_INT)fieldoffset
+             || v->next == NULL)
+           break;
+
+         v = v->next;
+         fieldoffset = v->offset;
        }
+      while (1);
     }
 }
 
@@ -2321,8 +2357,8 @@ rewrite_constraints (constraint_graph_t graph,
     {
       struct constraint_expr lhs = c->lhs;
       struct constraint_expr rhs = c->rhs;
-      unsigned int lhsvar = find (get_varinfo_fc (lhs.var)->id);
-      unsigned int rhsvar = find (get_varinfo_fc (rhs.var)->id);
+      unsigned int lhsvar = find (lhs.var);
+      unsigned int rhsvar = find (rhs.var);
       unsigned int lhsnode, rhsnode;
       unsigned int lhslabel, rhslabel;
 
@@ -2512,11 +2548,10 @@ solve_graph (constraint_graph_t graph)
 
              solution_empty = bitmap_empty_p (solution);
 
-             if (!solution_empty
-                 /* Do not propagate the ESCAPED solutions.  */
-                 && i != find (escaped_id))
+             if (!solution_empty)
                {
                  bitmap_iterator bi;
+                 unsigned eff_escaped_id = find (escaped_id);
 
                  /* Propagate solution to all successors.  */
                  EXECUTE_IF_IN_NONNULL_BITMAP (graph->succs[i],
@@ -2533,7 +2568,12 @@ solve_graph (constraint_graph_t graph)
                      if (to == i)
                        continue;
 
-                     flag = set_union_with_increment (tmp, pts, 0);
+                     /* If we propagate from ESCAPED use ESCAPED as
+                        placeholder.  */
+                     if (i == eff_escaped_id)
+                       flag = bitmap_set_bit (tmp, escaped_id);
+                     else
+                       flag = set_union_with_increment (tmp, pts, 0);
 
                      if (flag)
                        {
@@ -2710,20 +2750,18 @@ process_constraint (constraint_t t)
   gcc_assert (rhs.var < VEC_length (varinfo_t, varmap));
   gcc_assert (lhs.var < VEC_length (varinfo_t, varmap));
 
-  /* ANYTHING == ANYTHING is pointless.  */
-  if (lhs.var == anything_id && rhs.var == anything_id)
-    return;
+  /* If we didn't get any useful constraint from the lhs we get
+     &ANYTHING as fallback from get_constraint_for.  Deal with
+     it here by turning it into *ANYTHING.  */
+  if (lhs.type == ADDRESSOF
+      && lhs.var == anything_id)
+    lhs.type = DEREF;
+
+  /* ADDRESSOF on the lhs is invalid.  */
+  gcc_assert (lhs.type != ADDRESSOF);
 
-  /* If we have &ANYTHING = something, convert to SOMETHING = &ANYTHING) */
-  else if (lhs.var == anything_id && lhs.type == ADDRESSOF)
-    {
-      rhs = t->lhs;
-      t->lhs = t->rhs;
-      t->rhs = rhs;
-      process_constraint (t);
-    }
   /* This can happen in our IR with things like n->a = *p */
-  else if (rhs.type == DEREF && lhs.type == DEREF && rhs.var != anything_id)
+  if (rhs.type == DEREF && lhs.type == DEREF && rhs.var != anything_id)
     {
       /* Split into tmp = *rhs, *lhs = tmp */
       tree rhsdecl = get_varinfo (rhs.var)->decl;
@@ -2801,7 +2839,7 @@ get_constraint_for_ptr_offset (tree ptr, tree offset,
 {
   struct constraint_expr *c;
   unsigned int j, n;
-  unsigned HOST_WIDE_INT rhsunitoffset, rhsoffset;
+  HOST_WIDE_INT rhsunitoffset, rhsoffset;
 
   /* If we do not do field-sensitive PTA adding offsets to pointers
      does not change the points-to solution.  */
@@ -2814,30 +2852,16 @@ get_constraint_for_ptr_offset (tree ptr, tree offset,
   /* If the offset is not a non-negative integer constant that fits
      in a HOST_WIDE_INT, we have to fall back to a conservative
      solution which includes all sub-fields of all pointed-to
-     variables of ptr.
-     ???  As we do not have the ability to express this, fall back
-     to anything.  */
-  if (!host_integerp (offset, 1))
-    {
-      struct constraint_expr temp;
-      temp.var = anything_id;
-      temp.type = SCALAR;
-      temp.offset = 0;
-      VEC_safe_push (ce_s, heap, *results, &temp);
-      return;
-    }
-
-  /* Make sure the bit-offset also fits.  */
-  rhsunitoffset = TREE_INT_CST_LOW (offset);
-  rhsoffset = rhsunitoffset * BITS_PER_UNIT;
-  if (rhsunitoffset != rhsoffset / BITS_PER_UNIT)
+     variables of ptr.  */
+  if (!host_integerp (offset, 0))
+    rhsoffset = UNKNOWN_OFFSET;
+  else
     {
-      struct constraint_expr temp;
-      temp.var = anything_id;
-      temp.type = SCALAR;
-      temp.offset = 0;
-      VEC_safe_push (ce_s, heap, *results, &temp);
-      return;
+      /* Make sure the bit-offset also fits.  */
+      rhsunitoffset = TREE_INT_CST_LOW (offset);
+      rhsoffset = rhsunitoffset * BITS_PER_UNIT;
+      if (rhsunitoffset != rhsoffset / BITS_PER_UNIT)
+       rhsoffset = UNKNOWN_OFFSET;
     }
 
   get_constraint_for (ptr, results);
@@ -2854,36 +2878,49 @@ get_constraint_for_ptr_offset (tree ptr, tree offset,
       curr = get_varinfo (c->var);
 
       if (c->type == ADDRESSOF
-         && !curr->is_full_var)
+         /* If this varinfo represents a full variable just use it.  */
+         && curr->is_full_var)
+       c->offset = 0;
+      else if (c->type == ADDRESSOF
+              /* If we do not know the offset add all subfields.  */
+              && rhsoffset == UNKNOWN_OFFSET)
+       {
+         varinfo_t temp = lookup_vi_for_tree (curr->decl);
+         do
+           {
+             struct constraint_expr c2;
+             c2.var = temp->id;
+             c2.type = ADDRESSOF;
+             c2.offset = 0;
+             VEC_safe_push (ce_s, heap, *results, &c2);
+             temp = temp->next;
+           }
+         while (temp);
+       }
+      else if (c->type == ADDRESSOF)
        {
-         varinfo_t temp, curr = get_varinfo (c->var);
+         varinfo_t temp;
+         unsigned HOST_WIDE_INT offset = curr->offset + rhsoffset;
 
          /* Search the sub-field which overlaps with the
-            pointed-to offset.  As we deal with positive offsets
-            only, we can start the search from the current variable.  */
-         temp = first_vi_for_offset (curr, curr->offset + rhsoffset);
-
-         /* If the result is outside of the variable we have to provide
-            a conservative result, as the variable is still reachable
-            from the resulting pointer (even though it technically
-            cannot point to anything).  The last sub-field is such
-            a conservative result.
+            pointed-to offset.  If the result is outside of the variable
+            we have to provide a conservative result, as the variable is
+            still reachable from the resulting pointer (even though it
+            technically cannot point to anything).  The last and first
+            sub-fields are such conservative results.
             ???  If we always had a sub-field for &object + 1 then
             we could represent this in a more precise way.  */
-         if (temp == NULL)
-           {
-             temp = curr;
-             while (temp->next != NULL)
-               temp = temp->next;
-             continue;
-           }
+         if (rhsoffset < 0
+             && curr->offset < offset)
+           offset = 0;
+         temp = first_or_preceding_vi_for_offset (curr, offset);
 
          /* If the found variable is not exactly at the pointed to
             result, we have to include the next variable in the
             solution as well.  Otherwise two increments by offset / 2
             do not result in the same or a conservative superset
             solution.  */
-         if (temp->offset != curr->offset + rhsoffset
+         if (temp->offset != offset
              && temp->next != NULL)
            {
              struct constraint_expr c2;
@@ -2895,10 +2932,6 @@ get_constraint_for_ptr_offset (tree ptr, tree offset,
          c->var = temp->id;
          c->offset = 0;
        }
-      else if (c->type == ADDRESSOF
-              /* If this varinfo represents a full variable just use it.  */
-              && curr->is_full_var)
-       c->offset = 0;
       else
        c->offset = rhsoffset;
     }
@@ -2944,10 +2977,6 @@ get_constraint_for_component_ref (tree t, VEC(ce_s, heap) **results,
   gcc_assert (VEC_length (ce_s, *results) == 1);
   result = VEC_last (ce_s, *results);
 
-  /* This can also happen due to weird offsetof type macros.  */
-  if (TREE_CODE (t) != ADDR_EXPR && result->type == ADDRESSOF)
-    result->type = SCALAR;
-
   if (result->type == SCALAR
       && get_varinfo (result->var)->is_full_var)
     /* For single-field vars do not bother about the offset.  */
@@ -3011,15 +3040,20 @@ get_constraint_for_component_ref (tree t, VEC(ce_s, heap) **results,
        if (dump_file && (dump_flags & TDF_DETAILS))
          fprintf (dump_file, "Access to past the end of variable, ignoring\n");
     }
-  else if (bitmaxsize == -1)
+  else if (result->type == DEREF)
     {
-      /* We can't handle DEREF constraints with unknown size, we'll
-        get the wrong answer.  Punt and return anything.  */
-      result->var = anything_id;
-      result->offset = 0;
+      /* If we do not know exactly where the access goes say so.  Note
+        that only for non-structure accesses we know that we access
+        at most one subfiled of any variable.  */
+      if (bitpos == -1
+         || bitsize != bitmaxsize
+         || AGGREGATE_TYPE_P (TREE_TYPE (orig_t)))
+       result->offset = UNKNOWN_OFFSET;
+      else
+       result->offset = bitpos;
     }
   else
-    result->offset = bitpos;
+    gcc_unreachable ();
 }
 
 
@@ -3074,8 +3108,11 @@ get_constraint_for_1 (tree t, VEC (ce_s, heap) **results, bool address_p)
      It is not worth adding a new option or renaming the existing one,
      since this case is relatively obscure.  */
   if (flag_delete_null_pointer_checks
-      && TREE_CODE (t) == INTEGER_CST
-      && integer_zerop (t))
+      && ((TREE_CODE (t) == INTEGER_CST
+          && integer_zerop (t))
+         /* The only valid CONSTRUCTORs in gimple with pointer typed
+            elements are zero-initializer.  */
+         || TREE_CODE (t) == CONSTRUCTOR))
     {
       temp.var = nothing_id;
       temp.type = ADDRESSOF;
@@ -3137,6 +3174,10 @@ get_constraint_for_1 (tree t, VEC (ce_s, heap) **results, bool address_p)
          case COMPONENT_REF:
            get_constraint_for_component_ref (t, results, address_p);
            return;
+         case VIEW_CONVERT_EXPR:
+           get_constraint_for_1 (TREE_OPERAND (t, 0), results, address_p);
+           return;
+         /* We are missing handling for TARGET_MEM_REF here.  */
          default:;
          }
        break;
@@ -3179,277 +3220,73 @@ get_constraint_for (tree t, VEC (ce_s, heap) **results)
   get_constraint_for_1 (t, results, false);
 }
 
-/* Handle the structure copy case where we have a simple structure copy
-   between LHS and RHS that is of SIZE (in bits)
-
-   For each field of the lhs variable (lhsfield)
-     For each field of the rhs variable at lhsfield.offset (rhsfield)
-       add the constraint lhsfield = rhsfield
-
-   If we fail due to some kind of type unsafety or other thing we
-   can't handle, return false.  We expect the caller to collapse the
-   variable in that case.  */
-
-static bool
-do_simple_structure_copy (const struct constraint_expr lhs,
-                         const struct constraint_expr rhs,
-                         const unsigned HOST_WIDE_INT size)
-{
-  varinfo_t p = get_varinfo (lhs.var);
-  unsigned HOST_WIDE_INT pstart, last;
-  pstart = p->offset;
-  last = p->offset + size;
-  for (; p && p->offset < last; p = p->next)
-    {
-      varinfo_t q;
-      struct constraint_expr templhs = lhs;
-      struct constraint_expr temprhs = rhs;
-      unsigned HOST_WIDE_INT fieldoffset;
-
-      templhs.var = p->id;
-      q = get_varinfo (temprhs.var);
-      fieldoffset = p->offset - pstart;
-      q = first_vi_for_offset (q, q->offset + fieldoffset);
-      if (!q)
-       return false;
-      temprhs.var = q->id;
-      process_constraint (new_constraint (templhs, temprhs));
-    }
-  return true;
-}
-
-
-/* Handle the structure copy case where we have a  structure copy between a
-   aggregate on the LHS and a dereference of a pointer on the RHS
-   that is of SIZE (in bits)
-
-   For each field of the lhs variable (lhsfield)
-       rhs.offset = lhsfield->offset
-       add the constraint lhsfield = rhs
-*/
-
-static void
-do_rhs_deref_structure_copy (const struct constraint_expr lhs,
-                            const struct constraint_expr rhs,
-                            const unsigned HOST_WIDE_INT size)
-{
-  varinfo_t p = get_varinfo (lhs.var);
-  unsigned HOST_WIDE_INT pstart,last;
-  pstart = p->offset;
-  last = p->offset + size;
-
-  for (; p && p->offset < last; p = p->next)
-    {
-      varinfo_t q;
-      struct constraint_expr templhs = lhs;
-      struct constraint_expr temprhs = rhs;
-      unsigned HOST_WIDE_INT fieldoffset;
-
-
-      if (templhs.type == SCALAR)
-       templhs.var = p->id;
-      else
-       templhs.offset = p->offset;
-
-      q = get_varinfo (temprhs.var);
-      fieldoffset = p->offset - pstart;
-      temprhs.offset += fieldoffset;
-      process_constraint (new_constraint (templhs, temprhs));
-    }
-}
-
-/* Handle the structure copy case where we have a structure copy
-   between an aggregate on the RHS and a dereference of a pointer on
-   the LHS that is of SIZE (in bits)
-
-   For each field of the rhs variable (rhsfield)
-       lhs.offset = rhsfield->offset
-       add the constraint lhs = rhsfield
-*/
-
-static void
-do_lhs_deref_structure_copy (const struct constraint_expr lhs,
-                            const struct constraint_expr rhs,
-                            const unsigned HOST_WIDE_INT size)
-{
-  varinfo_t p = get_varinfo (rhs.var);
-  unsigned HOST_WIDE_INT pstart,last;
-  pstart = p->offset;
-  last = p->offset + size;
-
-  for (; p && p->offset < last; p = p->next)
-    {
-      varinfo_t q;
-      struct constraint_expr templhs = lhs;
-      struct constraint_expr temprhs = rhs;
-      unsigned HOST_WIDE_INT fieldoffset;
-
-
-      if (temprhs.type == SCALAR)
-       temprhs.var = p->id;
-      else
-       temprhs.offset = p->offset;
-
-      q = get_varinfo (templhs.var);
-      fieldoffset = p->offset - pstart;
-      templhs.offset += fieldoffset;
-      process_constraint (new_constraint (templhs, temprhs));
-    }
-}
-
-/* Sometimes, frontends like to give us bad type information.  This
-   function will collapse all the fields from VAR to the end of VAR,
-   into VAR, so that we treat those fields as a single variable.
-   We return the variable they were collapsed into.  */
-
-static unsigned int
-collapse_rest_of_var (unsigned int var)
-{
-  varinfo_t currvar = get_varinfo (var);
-  varinfo_t field;
-
-  for (field = currvar->next; field; field = field->next)
-    {
-      if (dump_file)
-       fprintf (dump_file, "Type safety: Collapsing var %s into %s\n",
-                field->name, currvar->name);
-
-      gcc_assert (field->collapsed_to == 0);
-      field->collapsed_to = currvar->id;
-    }
-
-  currvar->next = NULL;
-  currvar->size = currvar->fullsize - currvar->offset;
-
-  return currvar->id;
-}
-
 /* Handle aggregate copies by expanding into copies of the respective
    fields of the structures.  */
 
 static void
 do_structure_copy (tree lhsop, tree rhsop)
 {
-  struct constraint_expr lhs, rhs, tmp;
+  struct constraint_expr *lhsp, *rhsp;
   VEC (ce_s, heap) *lhsc = NULL, *rhsc = NULL;
-  varinfo_t p;
-  unsigned HOST_WIDE_INT lhssize;
-  unsigned HOST_WIDE_INT rhssize;
-
-  /* Pretend we are taking the address of the constraint exprs.
-     We deal with walking the sub-fields ourselves.  */
-  get_constraint_for_1 (lhsop, &lhsc, true);
-  get_constraint_for_1 (rhsop, &rhsc, true);
-  gcc_assert (VEC_length (ce_s, lhsc) == 1);
-  gcc_assert (VEC_length (ce_s, rhsc) == 1);
-  lhs = *(VEC_last (ce_s, lhsc));
-  rhs = *(VEC_last (ce_s, rhsc));
-
-  VEC_free (ce_s, heap, lhsc);
-  VEC_free (ce_s, heap, rhsc);
-
-  /* If we have special var = x, swap it around.  */
-  if (lhs.var <= integer_id && !(get_varinfo (rhs.var)->is_special_var))
-    {
-      tmp = lhs;
-      lhs = rhs;
-      rhs = tmp;
-    }
-
-  /*  This is fairly conservative for the RHS == ADDRESSOF case, in that it's
-      possible it's something we could handle.  However, most cases falling
-      into this are dealing with transparent unions, which are slightly
-      weird. */
-  if (rhs.type == ADDRESSOF && !(get_varinfo (rhs.var)->is_special_var))
+  unsigned j;
+
+  get_constraint_for (lhsop, &lhsc);
+  get_constraint_for (rhsop, &rhsc);
+  lhsp = VEC_index (ce_s, lhsc, 0);
+  rhsp = VEC_index (ce_s, rhsc, 0);
+  if (lhsp->type == DEREF
+      || (lhsp->type == ADDRESSOF && lhsp->var == anything_id)
+      || rhsp->type == DEREF)
     {
-      rhs.type = ADDRESSOF;
-      rhs.var = anything_id;
+      struct constraint_expr tmp;
+      tree tmpvar = create_tmp_var_raw (ptr_type_node,
+                                       "structcopydereftmp");
+      tmp.var = get_vi_for_tree (tmpvar)->id;
+      tmp.type = SCALAR;
+      tmp.offset = 0;
+      for (j = 0; VEC_iterate (ce_s, rhsc, j, rhsp); ++j)
+       process_constraint (new_constraint (tmp, *rhsp));
+      for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); ++j)
+       process_constraint (new_constraint (*lhsp, tmp));
     }
-
-  /* If the RHS is a special var, or an addressof, set all the LHS fields to
-     that special var.  */
-  if (rhs.var <= integer_id)
+  else if (lhsp->type == SCALAR
+          && (rhsp->type == SCALAR
+              || rhsp->type == ADDRESSOF))
     {
-      for (p = get_varinfo (lhs.var); p; p = p->next)
+      tree lhsbase, rhsbase;
+      HOST_WIDE_INT lhssize, lhsmaxsize, lhsoffset;
+      HOST_WIDE_INT rhssize, rhsmaxsize, rhsoffset;
+      unsigned k = 0;
+      lhsbase = get_ref_base_and_extent (lhsop, &lhsoffset,
+                                        &lhssize, &lhsmaxsize);
+      rhsbase = get_ref_base_and_extent (rhsop, &rhsoffset,
+                                        &rhssize, &rhsmaxsize);
+      for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp);)
        {
-         struct constraint_expr templhs = lhs;
-         struct constraint_expr temprhs = rhs;
-
-         if (templhs.type == SCALAR )
-           templhs.var = p->id;
+         varinfo_t lhsv, rhsv;
+         rhsp = VEC_index (ce_s, rhsc, k);
+         lhsv = get_varinfo (lhsp->var);
+         rhsv = get_varinfo (rhsp->var);
+         if (lhsv->may_have_pointers
+             && ranges_overlap_p (lhsv->offset + rhsoffset, lhsv->size,
+                                  rhsv->offset + lhsoffset, rhsv->size))
+           process_constraint (new_constraint (*lhsp, *rhsp));
+         if (lhsv->offset + rhsoffset + lhsv->size
+             > rhsv->offset + lhsoffset + rhsv->size)
+           {
+             ++k;
+             if (k >= VEC_length (ce_s, rhsc))
+               break;
+           }
          else
-           templhs.offset += p->offset;
-         process_constraint (new_constraint (templhs, temprhs));
+           ++j;
        }
     }
   else
-    {
-      tree rhstype = TREE_TYPE (rhsop);
-      tree lhstype = TREE_TYPE (lhsop);
-      tree rhstypesize;
-      tree lhstypesize;
-
-      lhstypesize = DECL_P (lhsop) ? DECL_SIZE (lhsop) : TYPE_SIZE (lhstype);
-      rhstypesize = DECL_P (rhsop) ? DECL_SIZE (rhsop) : TYPE_SIZE (rhstype);
-
-      /* If we have a variably sized types on the rhs or lhs, and a deref
-        constraint, add the constraint, lhsconstraint = &ANYTHING.
-        This is conservatively correct because either the lhs is an unknown
-        sized var (if the constraint is SCALAR), or the lhs is a DEREF
-        constraint, and every variable it can point to must be unknown sized
-        anyway, so we don't need to worry about fields at all.  */
-      if ((rhs.type == DEREF && TREE_CODE (rhstypesize) != INTEGER_CST)
-         || (lhs.type == DEREF && TREE_CODE (lhstypesize) != INTEGER_CST))
-       {
-         rhs.var = anything_id;
-         rhs.type = ADDRESSOF;
-         rhs.offset = 0;
-         process_constraint (new_constraint (lhs, rhs));
-         return;
-       }
-
-      /* The size only really matters insofar as we don't set more or less of
-        the variable.  If we hit an unknown size var, the size should be the
-        whole darn thing.  */
-      if (get_varinfo (rhs.var)->is_unknown_size_var)
-       rhssize = ~0;
-      else
-       rhssize = TREE_INT_CST_LOW (rhstypesize);
-
-      if (get_varinfo (lhs.var)->is_unknown_size_var)
-       lhssize = ~0;
-      else
-       lhssize = TREE_INT_CST_LOW (lhstypesize);
-
-
-      if (rhs.type == SCALAR && lhs.type == SCALAR)
-       {
-         if (!do_simple_structure_copy (lhs, rhs, MIN (lhssize, rhssize)))
-           {
-             lhs.var = collapse_rest_of_var (get_varinfo_fc (lhs.var)->id);
-             rhs.var = collapse_rest_of_var (get_varinfo_fc (rhs.var)->id);
-             lhs.offset = 0;
-             rhs.offset = 0;
-             lhs.type = SCALAR;
-             rhs.type = SCALAR;
-             process_constraint (new_constraint (lhs, rhs));
-           }
-       }
-      else if (lhs.type != DEREF && rhs.type == DEREF)
-       do_rhs_deref_structure_copy (lhs, rhs, MIN (lhssize, rhssize));
-      else if (lhs.type == DEREF && rhs.type != DEREF)
-       do_lhs_deref_structure_copy (lhs, rhs, MIN (lhssize, rhssize));
-      else
-       {
-         tree pointedtotype = lhstype;
-         tree tmpvar;
+    gcc_unreachable ();
 
-         gcc_assert (rhs.type == DEREF && lhs.type == DEREF);
-         tmpvar = create_tmp_var_raw (pointedtotype, "structcopydereftmp");
-         do_structure_copy (tmpvar, rhsop);
-         do_structure_copy (lhsop, tmpvar);
-       }
-    }
+  VEC_free (ce_s, heap, lhsc);
+  VEC_free (ce_s, heap, rhsc);
 }
 
 /* Create a constraint ID = OP.  */
@@ -3503,10 +3340,10 @@ handle_rhs_call (gimple stmt, VEC(ce_s, heap) **results)
   if (gimple_call_chain (stmt))
     make_escape_constraint (gimple_call_chain (stmt));
 
-  /* Regular functions return escaped addresses.  */
-  rhsc.var = escaped_id;
+  /* Regular functions return nonlocal memory.  */
+  rhsc.var = nonlocal_id;
   rhsc.offset = 0;
-  rhsc.type = ADDRESSOF;
+  rhsc.type = SCALAR;
   VEC_safe_push (ce_s, heap, *results, &rhsc);
 }
 
@@ -3663,7 +3500,7 @@ handle_pure_call (gimple stmt, VEC(ce_s, heap) **results)
       need_callused = true;
     }
 
-  /* Pure functions may return callused and escaped memory.  */
+  /* Pure functions may return callused and nonlocal memory.  */
   if (need_callused)
     {
       rhsc.var = callused_id;
@@ -3671,9 +3508,9 @@ handle_pure_call (gimple stmt, VEC(ce_s, heap) **results)
       rhsc.type = SCALAR;
       VEC_safe_push (ce_s, heap, *results, &rhsc);
     }
-  rhsc.var = escaped_id;
+  rhsc.var = nonlocal_id;
   rhsc.offset = 0;
-  rhsc.type = ADDRESSOF;
+  rhsc.type = SCALAR;
   VEC_safe_push (ce_s, heap, *results, &rhsc);
 }
 
@@ -3922,58 +3759,128 @@ find_func_aliases (gimple origt)
     }
   else if (stmt_escape_type == ESCAPE_TO_ASM)
     {
-      unsigned i;
-      for (i = 0; i < gimple_asm_noutputs (t); ++i)
+      unsigned i, noutputs;
+      const char **oconstraints;
+      const char *constraint;
+      bool allows_mem, allows_reg, is_inout;
+
+      noutputs = gimple_asm_noutputs (t);
+      oconstraints = XALLOCAVEC (const char *, noutputs);
+
+      for (i = 0; i < noutputs; ++i)
        {
-         tree op = TREE_VALUE (gimple_asm_output_op (t, i));
+         tree link = gimple_asm_output_op (t, i);
+         tree op = TREE_VALUE (link);
+
+         constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
+         oconstraints[i] = constraint;
+         parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
+                                  &allows_reg, &is_inout);
+
+         /* A memory constraint makes the address of the operand escape.  */
+         if (!allows_reg && allows_mem)
+           make_escape_constraint (build_fold_addr_expr (op));
+
+         /* The asm may read global memory, so outputs may point to
+            any global memory.  */
          if (op && could_have_pointers (op))
-           /* Strictly we'd only need the constraints from ESCAPED and
-              NONLOCAL.  */
-           make_escape_constraint (op);
+           {
+             VEC(ce_s, heap) *lhsc = NULL;
+             struct constraint_expr rhsc, *lhsp;
+             unsigned j;
+             get_constraint_for (op, &lhsc);
+             rhsc.var = nonlocal_id;
+             rhsc.offset = 0;
+             rhsc.type = SCALAR;
+             for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
+               process_constraint (new_constraint (*lhsp, rhsc));
+             VEC_free (ce_s, heap, lhsc);
+           }
        }
       for (i = 0; i < gimple_asm_ninputs (t); ++i)
        {
-         tree op = TREE_VALUE (gimple_asm_input_op (t, i));
-         if (op && could_have_pointers (op))
-           /* Strictly we'd only need the constraint to ESCAPED.  */
+         tree link = gimple_asm_input_op (t, i);
+         tree op = TREE_VALUE (link);
+
+         constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
+
+         parse_input_constraint (&constraint, 0, 0, noutputs, 0, oconstraints,
+                                 &allows_mem, &allows_reg);
+
+         /* A memory constraint makes the address of the operand escape.  */
+         if (!allows_reg && allows_mem)
+           make_escape_constraint (build_fold_addr_expr (op));
+         /* Strictly we'd only need the constraint to ESCAPED if
+            the asm clobbers memory, otherwise using CALLUSED
+            would be enough.  */
+         else if (op && could_have_pointers (op))
            make_escape_constraint (op);
        }
     }
 
-  /* After promoting variables and computing aliasing we will
-     need to re-scan most statements.  FIXME: Try to minimize the
-     number of statements re-scanned.  It's not really necessary to
-     re-scan *all* statements.  */
-  if (!in_ipa_mode)
-    gimple_set_modified (origt, true);
   VEC_free (ce_s, heap, rhsc);
   VEC_free (ce_s, heap, lhsc);
 }
 
 
 /* Find the first varinfo in the same variable as START that overlaps with
-   OFFSET.
-   Effectively, walk the chain of fields for the variable START to find the
-   first field that overlaps with OFFSET.
-   Return NULL if we can't find one.  */
+   OFFSET.  Return NULL if we can't find one.  */
 
 static varinfo_t
 first_vi_for_offset (varinfo_t start, unsigned HOST_WIDE_INT offset)
 {
-  varinfo_t curr = start;
-  while (curr)
+  /* If the offset is outside of the variable, bail out.  */
+  if (offset >= start->fullsize)
+    return NULL;
+
+  /* If we cannot reach offset from start, lookup the first field
+     and start from there.  */
+  if (start->offset > offset)
+    start = lookup_vi_for_tree (start->decl);
+
+  while (start)
     {
       /* We may not find a variable in the field list with the actual
         offset when when we have glommed a structure to a variable.
         In that case, however, offset should still be within the size
         of the variable. */
-      if (offset >= curr->offset && offset < (curr->offset +  curr->size))
-       return curr;
-      curr = curr->next;
+      if (offset >= start->offset
+         && offset < (start->offset + start->size))
+       return start;
+
+      start= start->next;
     }
+
   return NULL;
 }
 
+/* Find the first varinfo in the same variable as START that overlaps with
+   OFFSET.  If there is no such varinfo the varinfo directly preceding
+   OFFSET is returned.  */
+
+static varinfo_t
+first_or_preceding_vi_for_offset (varinfo_t start,
+                                 unsigned HOST_WIDE_INT offset)
+{
+  /* If we cannot reach offset from start, lookup the first field
+     and start from there.  */
+  if (start->offset > offset)
+    start = lookup_vi_for_tree (start->decl);
+
+  /* We may not find a variable in the field list with the actual
+     offset when when we have glommed a structure to a variable.
+     In that case, however, offset should still be within the size
+     of the variable.
+     If we got beyond the offset we look for return the field
+     directly preceding offset which may be the last field.  */
+  while (start->next
+        && offset >= start->offset
+        && !(offset < (start->offset + start->size)))
+    start = start->next;
+
+  return start;
+}
+
 
 /* Insert the varinfo FIELD into the field list for BASE, at the front
    of the list.  */
@@ -4083,7 +3990,7 @@ var_can_have_subvars (const_tree v)
     return false;
 
   /* Non decls or memory tags can never have subvars.  */
-  if (!DECL_P (v) || MTAG_P (v))
+  if (!DECL_P (v))
     return false;
 
   /* Aggregates without overlapping fields can have subvars.  */
@@ -4197,18 +4104,35 @@ make_constraint_from (varinfo_t vi, int from)
   process_constraint (new_constraint (lhs, rhs));
 }
 
-/* Count the number of arguments DECL has, and set IS_VARARGS to true
-   if it is a varargs function.  */
+/* Create a constraint ID = FROM.  */
 
-static unsigned int
-count_num_arguments (tree decl, bool *is_varargs)
+static void
+make_copy_constraint (varinfo_t vi, int from)
 {
-  unsigned int i = 0;
-  tree t;
+  struct constraint_expr lhs, rhs;
 
-  for (t = TYPE_ARG_TYPES (TREE_TYPE (decl));
-       t;
-       t = TREE_CHAIN (t))
+  lhs.var = vi->id;
+  lhs.offset = 0;
+  lhs.type = SCALAR;
+
+  rhs.var = from;
+  rhs.offset = 0;
+  rhs.type = SCALAR;
+  process_constraint (new_constraint (lhs, rhs));
+}
+
+/* Count the number of arguments DECL has, and set IS_VARARGS to true
+   if it is a varargs function.  */
+
+static unsigned int
+count_num_arguments (tree decl, bool *is_varargs)
+{
+  unsigned int i = 0;
+  tree t;
+
+  for (t = TYPE_ARG_TYPES (TREE_TYPE (decl));
+       t;
+       t = TREE_CHAIN (t))
     {
       if (TREE_VALUE (t) == void_type_node)
        break;
@@ -4398,7 +4322,7 @@ create_variable_info_for (tree decl, const char *name)
          && var_ann (decl)->noalias_state == NO_ALIAS_ANYTHING)
        make_constraint_from (vi, vi->id);
       else
-       make_constraint_from (vi, escaped_id);
+       make_copy_constraint (vi, nonlocal_id);
     }
 
   stats.total_vars++;
@@ -4480,7 +4404,7 @@ create_variable_info_for (tree decl, const char *name)
          VEC_safe_push (varinfo_t, heap, varmap, newvi);
          if (is_global && (!flag_whole_program || !in_ipa_mode)
              && newvi->may_have_pointers)
-           make_constraint_from (newvi, escaped_id);
+           make_copy_constraint (newvi, nonlocal_id);
 
          stats.total_vars++;
        }
@@ -4495,7 +4419,7 @@ create_variable_info_for (tree decl, const char *name)
 
 /* Print out the points-to solution for VAR to FILE.  */
 
-void
+static void
 dump_solution_for_var (FILE *file, unsigned int var)
 {
   varinfo_t vi = get_varinfo (var);
@@ -4615,7 +4539,7 @@ intra_create_variable_infos (void)
       varinfo_t p, result_vi = get_vi_for_tree (DECL_RESULT (cfun->decl));
 
       for (p = result_vi; p; p = p->next)
-        make_constraint_from (p, nonlocal_id);
+       make_constraint_from (p, nonlocal_id);
     }
 
   /* Add a constraint for the incoming static chain parameter.  */
@@ -4698,25 +4622,20 @@ shared_bitmap_add (bitmap pt_vars)
 }
 
 
-/* Set bits in INTO corresponding to the variable uids in solution set
-   FROM, which came from variable PTR.
-   For variables that are actually dereferenced, we also use type
-   based alias analysis to prune the points-to sets.
-   IS_DEREFED is true if PTR was directly dereferenced, which we use to
-   help determine whether we are we are allowed to prune using TBAA.
-   If NO_TBAA_PRUNING is true, we do not perform any TBAA pruning of
-   the from set.  Returns the number of pruned variables.  */
+/* Set bits in INTO corresponding to the variable uids in solution set FROM.
+   If MEM_ALIAS_SET is not zero, we also use type based alias analysis to
+   prune the points-to sets with this alias-set.
+   Returns the number of pruned variables and updates the vars_contains_global
+   member of *PT .  */
 
 static unsigned
-set_uids_in_ptset (tree ptr, bitmap into, bitmap from, bool is_derefed,
-                  bool no_tbaa_pruning)
+set_uids_in_ptset (bitmap into, bitmap from,
+                  alias_set_type mem_alias_set, struct pt_solution *pt)
 {
   unsigned int i;
   bitmap_iterator bi;
   unsigned pruned = 0;
 
-  gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
-
   EXECUTE_IF_SET_IN_BITMAP (from, 0, i, bi)
     {
       varinfo_t vi = get_varinfo (i);
@@ -4730,26 +4649,27 @@ set_uids_in_ptset (tree ptr, bitmap into, bitmap from, bool is_derefed,
          || TREE_CODE (vi->decl) == PARM_DECL
          || TREE_CODE (vi->decl) == RESULT_DECL)
        {
-         /* Just add VI->DECL to the alias set.
-            Don't type prune artificial vars or points-to sets
+         /* Don't type prune artificial vars or points-to sets
             for pointers that have not been dereferenced or with
             type-based pruning disabled.  */
-         if (vi->is_artificial_var
-             || !is_derefed
-             || no_tbaa_pruning
-             || vi->no_tbaa_pruning)
-           bitmap_set_bit (into, DECL_UID (vi->decl));
-         else
+         if (!vi->is_artificial_var
+             && !vi->no_tbaa_pruning
+             && mem_alias_set != 0)
            {
-             alias_set_type var_alias_set, mem_alias_set;
-             var_alias_set = get_alias_set (vi->decl);
-             mem_alias_set = get_alias_set (TREE_TYPE (TREE_TYPE (ptr)));
-             if (may_alias_p (SSA_NAME_VAR (ptr), mem_alias_set,
-                              vi->decl, var_alias_set, true))
-               bitmap_set_bit (into, DECL_UID (vi->decl));
-             else
-               ++pruned;
+             alias_set_type var_alias_set = get_alias_set (vi->decl);
+             if (mem_alias_set != var_alias_set
+                 && !alias_set_subset_of (mem_alias_set, var_alias_set))
+               {
+                 ++pruned;
+                 continue;
+               }
            }
+
+         /* Add the decl to the points-to set.  Note that the points-to
+            set contains global variables.  */
+         bitmap_set_bit (into, DECL_UID (vi->decl));
+         if (is_global_var (vi->decl))
+           pt->vars_contains_global = true;
        }
     }
 
@@ -4844,26 +4764,101 @@ emit_alias_warning (tree ptr)
     }
 }
 
-/* Given a pointer variable P, fill in its points-to set, or return
-   false if we can't.
-   Rather than return false for variables that point-to anything, we
-   instead find the corresponding SMT, and merge in its aliases.  In
-   addition to these aliases, we also set the bits for the SMT's
-   themselves and their subsets, as SMT's are still in use by
-   non-SSA_NAME's, and pruning may eliminate every one of their
-   aliases.  In such a case, if we did not include the right set of
-   SMT's in the points-to set of the variable, we'd end up with
-   statements that do not conflict but should.  */
+/* Compute the points-to solution *PT for the variable VI.
+   Prunes the points-to set based on TBAA rules if DO_TBAA_PRUNING
+   is true.  Returns the number of TBAA pruned variables from the
+   points-to set.  */
 
-bool
-find_what_p_points_to (tree p)
+static unsigned int
+find_what_var_points_to (varinfo_t vi, struct pt_solution *pt,
+                        bool do_tbaa_pruning)
 {
+  unsigned int i, pruned;
+  bitmap_iterator bi;
+  bitmap finished_solution;
+  bitmap result;
+  tree ptr = vi->decl;
+  alias_set_type mem_alias_set;
+
+  memset (pt, 0, sizeof (struct pt_solution));
+
+  /* This variable may have been collapsed, let's get the real
+     variable.  */
+  vi = get_varinfo (find (vi->id));
+
+  /* Translate artificial variables into SSA_NAME_PTR_INFO
+     attributes.  */
+  EXECUTE_IF_SET_IN_BITMAP (vi->solution, 0, i, bi)
+    {
+      varinfo_t vi = get_varinfo (i);
+
+      if (vi->is_artificial_var)
+       {
+         if (vi->id == nothing_id)
+           pt->null = 1;
+         else if (vi->id == escaped_id)
+           pt->escaped = 1;
+         else if (vi->id == callused_id)
+           gcc_unreachable ();
+         else if (vi->id == nonlocal_id)
+           pt->nonlocal = 1;
+         else if (vi->is_heap_var)
+           /* We represent heapvars in the points-to set properly.  */
+           ;
+         else if (vi->id == anything_id
+                  || vi->id == readonly_id
+                  || vi->id == integer_id)
+           pt->anything = 1;
+       }
+    }
+
+  /* Instead of doing extra work, simply do not create
+     elaborate points-to information for pt_anything pointers.  */
+  if (pt->anything)
+    return 0;
+
+  /* Share the final set of variables when possible.  */
+  finished_solution = BITMAP_GGC_ALLOC ();
+  stats.points_to_sets_created++;
+
+  if (TREE_CODE (ptr) == SSA_NAME)
+    ptr = SSA_NAME_VAR (ptr);
+
+  /* If the pointer decl is marked that no TBAA is to be applied,
+     do not do tbaa pruning.  */
+  if (!do_tbaa_pruning
+      || DECL_NO_TBAA_P (ptr))
+    mem_alias_set = 0;
+  else
+    mem_alias_set = get_deref_alias_set (ptr);
+  pruned = set_uids_in_ptset (finished_solution, vi->solution,
+                             mem_alias_set, pt);
+  result = shared_bitmap_lookup (finished_solution);
+  if (!result)
+    {
+      shared_bitmap_add (finished_solution);
+      pt->vars = finished_solution;
+    }
+  else
+    {
+      pt->vars = result;
+      bitmap_clear (finished_solution);
+    }
+
+  return pruned;
+}
+
+/* Given a pointer variable P, fill in its points-to set.  Apply
+   type-based pruning if IS_DEREFERENCED is true.  */
+
+static void
+find_what_p_points_to (tree p, bool is_dereferenced)
+{
+  struct ptr_info_def *pi;
+  unsigned int pruned;
   tree lookup_p = p;
   varinfo_t vi;
 
-  if (!have_alias_info)
-    return false;
-
   /* For parameters, get at the points-to set for the actual parm
      decl.  */
   if (TREE_CODE (p) == SSA_NAME
@@ -4872,225 +4867,198 @@ find_what_p_points_to (tree p)
     lookup_p = SSA_NAME_VAR (p);
 
   vi = lookup_vi_for_tree (lookup_p);
-  if (vi)
-    {
-      if (vi->is_artificial_var)
-       return false;
+  if (!vi)
+    return;
+
+  pi = get_ptr_info (p);
+  pruned = find_what_var_points_to (vi, &pi->pt, is_dereferenced);
 
-      /* See if this is a field or a structure.  */
-      if (vi->size != vi->fullsize)
+  if (!(pi->pt.anything || pi->pt.nonlocal || pi->pt.escaped)
+      && bitmap_empty_p (pi->pt.vars)
+      && pruned > 0
+      && is_dereferenced
+      && warn_strict_aliasing > 0
+      && !SSA_NAME_IS_DEFAULT_DEF (p))
+    {
+      if (dump_file && dump_flags & TDF_DETAILS)
        {
-         /* Nothing currently asks about structure fields directly,
-            but when they do, we need code here to hand back the
-            points-to set.  */
-         return false;
+         fprintf (dump_file, "alias warning for ");
+         print_generic_expr (dump_file, p, 0);
+         fprintf (dump_file, "\n");
        }
-      else
-       {
-         struct ptr_info_def *pi = get_ptr_info (p);
-         unsigned int i, pruned;
-         bitmap_iterator bi;
-         bool was_pt_anything = false;
-         bitmap finished_solution;
-         bitmap result;
+      emit_alias_warning (p);
+    }
+}
 
-         if (!pi->memory_tag_needed)
-           return false;
 
-         /* This variable may have been collapsed, let's get the real
-            variable.  */
-         vi = get_varinfo (find (vi->id));
+/* Query statistics for points-to solutions.  */
 
-         /* Translate artificial variables into SSA_NAME_PTR_INFO
-            attributes.  */
-         EXECUTE_IF_SET_IN_BITMAP (vi->solution, 0, i, bi)
-           {
-             varinfo_t vi = get_varinfo (i);
+static struct {
+  unsigned HOST_WIDE_INT pt_solution_includes_may_alias;
+  unsigned HOST_WIDE_INT pt_solution_includes_no_alias;
+  unsigned HOST_WIDE_INT pt_solutions_intersect_may_alias;
+  unsigned HOST_WIDE_INT pt_solutions_intersect_no_alias;
+} pta_stats;
 
-             if (vi->is_artificial_var)
-               {
-                 /* FIXME.  READONLY should be handled better so that
-                    flow insensitive aliasing can disregard writable
-                    aliases.  */
-                 if (vi->id == nothing_id)
-                   pi->pt_null = 1;
-                 else if (vi->id == anything_id
-                          || vi->id == nonlocal_id
-                          || vi->id == escaped_id)
-                   was_pt_anything = 1;
-                 else if (vi->id == callused_id)
-                   gcc_unreachable ();
-                 else if (vi->id == readonly_id)
-                   was_pt_anything = 1;
-                 else if (vi->id == integer_id)
-                   was_pt_anything = 1;
-                 else if (vi->is_heap_var)
-                   pi->pt_global_mem = 1;
-               }
-           }
+void
+dump_pta_stats (FILE *s)
+{
+  fprintf (s, "\nPTA query stats:\n");
+  fprintf (s, "  pt_solution_includes: "
+          HOST_WIDE_INT_PRINT_DEC" disambiguations, "
+          HOST_WIDE_INT_PRINT_DEC" queries\n",
+          pta_stats.pt_solution_includes_no_alias,
+          pta_stats.pt_solution_includes_no_alias
+          + pta_stats.pt_solution_includes_may_alias);
+  fprintf (s, "  pt_solutions_intersect: "
+          HOST_WIDE_INT_PRINT_DEC" disambiguations, "
+          HOST_WIDE_INT_PRINT_DEC" queries\n",
+          pta_stats.pt_solutions_intersect_no_alias,
+          pta_stats.pt_solutions_intersect_no_alias
+          + pta_stats.pt_solutions_intersect_may_alias);
+}
 
-         /* Instead of doing extra work, simply do not create
-            points-to information for pt_anything pointers.  This
-            will cause the operand scanner to fall back to the
-            type-based SMT and its aliases.  Which is the best
-            we could do here for the points-to set as well.  */
-         if (was_pt_anything)
-           return false;
 
-         /* Share the final set of variables when possible.  */
-         finished_solution = BITMAP_GGC_ALLOC ();
-         stats.points_to_sets_created++;
+/* Reset the points-to solution *PT to a conservative default
+   (point to anything).  */
 
-         pruned = set_uids_in_ptset (p, finished_solution, vi->solution,
-                                     pi->is_dereferenced,
-                                     vi->no_tbaa_pruning);
-         result = shared_bitmap_lookup (finished_solution);
+void
+pt_solution_reset (struct pt_solution *pt)
+{
+  memset (pt, 0, sizeof (struct pt_solution));
+  pt->anything = true;
+}
 
-         if (!result)
-           {
-             shared_bitmap_add (finished_solution);
-             pi->pt_vars = finished_solution;
-           }
-         else
-           {
-             pi->pt_vars = result;
-             bitmap_clear (finished_solution);
-           }
+/* Return true if the points-to solution *PT is empty.  */
 
-         if (bitmap_empty_p (pi->pt_vars))
-           {
-             pi->pt_vars = NULL;
-             if (pruned > 0
-                 && !pi->pt_null
-                 && pi->is_dereferenced
-                 && warn_strict_aliasing > 0
-                 && !SSA_NAME_IS_DEFAULT_DEF (p))
-               {
-                 if (dump_file && dump_flags & TDF_DETAILS)
-                   {
-                     fprintf (dump_file, "alias warning for ");
-                     print_generic_expr (dump_file, p, 0);
-                     fprintf (dump_file, "\n");
-                   }
-                 emit_alias_warning (p);
-               }
-           }
+static bool
+pt_solution_empty_p (struct pt_solution *pt)
+{
+  if (pt->anything
+      || pt->nonlocal)
+    return false;
 
-         return true;
-       }
-    }
+  if (pt->vars
+      && !bitmap_empty_p (pt->vars))
+    return false;
 
-  return false;
+  /* If the solution includes ESCAPED, check if that is empty.  */
+  if (pt->escaped
+      && !pt_solution_empty_p (&cfun->gimple_df->escaped))
+    return false;
+
+  return true;
 }
 
-/* Mark the ESCAPED solution as call clobbered.  Returns false if
-   pt_anything escaped which needs all locals that have their address
-   taken marked call clobbered as well.  */
+/* Return true if the points-to solution *PT includes global memory.  */
 
 bool
-clobber_what_escaped (void)
+pt_solution_includes_global (struct pt_solution *pt)
 {
-  varinfo_t vi;
-  unsigned int i;
-  bitmap_iterator bi;
+  if (pt->anything
+      || pt->nonlocal
+      || pt->vars_contains_global)
+    return true;
 
-  if (!have_alias_info)
-    return false;
+  if (pt->escaped)
+    return pt_solution_includes_global (&cfun->gimple_df->escaped);
 
-  /* This variable may have been collapsed, let's get the real
-     variable for escaped_id.  */
-  vi = get_varinfo (find (escaped_id));
+  return false;
+}
 
-  /* If call-used memory escapes we need to include it in the
-     set of escaped variables.  This can happen if a pure
-     function returns a pointer and this pointer escapes.  */
-  if (bitmap_bit_p (vi->solution, callused_id))
-    {
-      varinfo_t cu_vi = get_varinfo (find (callused_id));
-      bitmap_ior_into (vi->solution, cu_vi->solution);
-    }
+/* Return true if the points-to solution *PT includes the variable
+   declaration DECL.  */
 
-  /* Mark variables in the solution call-clobbered.  */
-  EXECUTE_IF_SET_IN_BITMAP (vi->solution, 0, i, bi)
-    {
-      varinfo_t vi = get_varinfo (i);
+static bool
+pt_solution_includes_1 (struct pt_solution *pt, const_tree decl)
+{
+  if (pt->anything)
+    return true;
 
-      if (vi->is_artificial_var)
-       {
-         /* nothing_id and readonly_id do not cause any
-            call clobber ops.  For anything_id and integer_id
-            we need to clobber all addressable vars.  */
-         if (vi->id == anything_id
-             || vi->id == integer_id)
-           return false;
-       }
+  if (pt->nonlocal
+      && is_global_var (decl))
+    return true;
 
-      /* Only artificial heap-vars are further interesting.  */
-      if (vi->is_artificial_var && !vi->is_heap_var)
-       continue;
+  if (pt->vars
+      && bitmap_bit_p (pt->vars, DECL_UID (decl)))
+    return true;
 
-      if ((TREE_CODE (vi->decl) == VAR_DECL
-          || TREE_CODE (vi->decl) == PARM_DECL
-          || TREE_CODE (vi->decl) == RESULT_DECL)
-         && !unmodifiable_var_p (vi->decl))
-       mark_call_clobbered (vi->decl, ESCAPE_TO_CALL);
-    }
+  /* If the solution includes ESCAPED, check it.  */
+  if (pt->escaped
+      && pt_solution_includes_1 (&cfun->gimple_df->escaped, decl))
+    return true;
 
-  return true;
+  return false;
 }
 
-/* Compute the call-used variables.  */
-
-void
-compute_call_used_vars (void)
+bool
+pt_solution_includes (struct pt_solution *pt, const_tree decl)
 {
-  varinfo_t vi;
-  unsigned int i;
-  bitmap_iterator bi;
-  bool has_anything_id = false;
-
-  if (!have_alias_info)
-    return;
+  bool res = pt_solution_includes_1 (pt, decl);
+  if (res)
+    ++pta_stats.pt_solution_includes_may_alias;
+  else
+    ++pta_stats.pt_solution_includes_no_alias;
+  return res;
+}
 
-  /* This variable may have been collapsed, let's get the real
-     variable for escaped_id.  */
-  vi = get_varinfo (find (callused_id));
+/* Return true if both points-to solutions PT1 and PT2 have a non-empty
+   intersection.  */
 
-  /* Mark variables in the solution call-clobbered.  */
-  EXECUTE_IF_SET_IN_BITMAP (vi->solution, 0, i, bi)
-    {
-      varinfo_t vi = get_varinfo (i);
+static bool
+pt_solutions_intersect_1 (struct pt_solution *pt1, struct pt_solution *pt2)
+{
+  if (pt1->anything || pt2->anything)
+    return true;
 
-      if (vi->is_artificial_var)
-       {
-         /* For anything_id and integer_id we need to make
-            all local addressable vars call-used.  */
-         if (vi->id == anything_id
-             || vi->id == integer_id)
-           has_anything_id = true;
-       }
+  /* If either points to unknown global memory and the other points to
+     any global memory they alias.  */
+  if ((pt1->nonlocal
+       && (pt2->nonlocal
+          || pt2->vars_contains_global))
+      || (pt2->nonlocal
+         && pt1->vars_contains_global))
+    return true;
 
-      /* Only artificial heap-vars are further interesting.  */
-      if (vi->is_artificial_var && !vi->is_heap_var)
-       continue;
+  /* Check the escaped solution if required.  */
+  if ((pt1->escaped || pt2->escaped)
+      && !pt_solution_empty_p (&cfun->gimple_df->escaped))
+    {
+      /* If both point to escaped memory and that solution
+        is not empty they alias.  */
+      if (pt1->escaped && pt2->escaped)
+       return true;
 
-      if ((TREE_CODE (vi->decl) == VAR_DECL
-          || TREE_CODE (vi->decl) == PARM_DECL
-          || TREE_CODE (vi->decl) == RESULT_DECL)
-         && !unmodifiable_var_p (vi->decl))
-       bitmap_set_bit (gimple_call_used_vars (cfun), DECL_UID (vi->decl));
+      /* If either points to escaped memory see if the escaped solution
+        intersects with the other.  */
+      if ((pt1->escaped
+          && pt_solutions_intersect_1 (&cfun->gimple_df->escaped, pt2))
+         || (pt2->escaped
+             && pt_solutions_intersect_1 (&cfun->gimple_df->escaped, pt1)))
+       return true;
     }
 
-  /* If anything is call-used, add all addressable locals to the set.  */
-  if (has_anything_id)
-    bitmap_ior_into (gimple_call_used_vars (cfun),
-                    gimple_addressable_vars (cfun));
+  /* Now both pointers alias if their points-to solution intersects.  */
+  return (pt1->vars
+         && pt2->vars
+         && bitmap_intersect_p (pt1->vars, pt2->vars));
+}
+
+bool
+pt_solutions_intersect (struct pt_solution *pt1, struct pt_solution *pt2)
+{
+  bool res = pt_solutions_intersect_1 (pt1, pt2);
+  if (res)
+    ++pta_stats.pt_solutions_intersect_may_alias;
+  else
+    ++pta_stats.pt_solutions_intersect_no_alias;
+  return res;
 }
 
 
 /* Dump points-to information to OUTFILE.  */
 
-void
+static void
 dump_sa_points_to_info (FILE *outfile)
 {
   unsigned int i;
@@ -5149,7 +5117,7 @@ init_base_vars (void)
 
   /* Create the ANYTHING variable, used to represent that a variable
      points to some unknown piece of memory.  */
-  anything_tree = create_tmp_var_raw (void_type_node, "ANYTHING");
+  anything_tree = create_tmp_var_raw (ptr_type_node, "ANYTHING");
   var_anything = new_var_info (anything_tree, anything_id, "ANYTHING");
   insert_vi_for_tree (anything_tree, var_anything);
   var_anything->is_artificial_var = 1;
@@ -5177,7 +5145,7 @@ init_base_vars (void)
 
   /* Create the READONLY variable, used to represent that a variable
      points to readonly memory.  */
-  readonly_tree = create_tmp_var_raw (void_type_node, "READONLY");
+  readonly_tree = create_tmp_var_raw (ptr_type_node, "READONLY");
   var_readonly = new_var_info (readonly_tree, readonly_id, "READONLY");
   var_readonly->is_artificial_var = 1;
   var_readonly->offset = 0;
@@ -5202,7 +5170,7 @@ init_base_vars (void)
 
   /* Create the ESCAPED variable, used to represent the set of escaped
      memory.  */
-  escaped_tree = create_tmp_var_raw (void_type_node, "ESCAPED");
+  escaped_tree = create_tmp_var_raw (ptr_type_node, "ESCAPED");
   var_escaped = new_var_info (escaped_tree, escaped_id, "ESCAPED");
   insert_vi_for_tree (escaped_tree, var_escaped);
   var_escaped->is_artificial_var = 1;
@@ -5213,18 +5181,9 @@ init_base_vars (void)
   VEC_safe_push (varinfo_t, heap, varmap, var_escaped);
   gcc_assert (VEC_index (varinfo_t, varmap, 3) == var_escaped);
 
-  /* ESCAPED = *ESCAPED, because escaped is may-deref'd at calls, etc.  */
-  lhs.type = SCALAR;
-  lhs.var = escaped_id;
-  lhs.offset = 0;
-  rhs.type = DEREF;
-  rhs.var = escaped_id;
-  rhs.offset = 0;
-  process_constraint (new_constraint (lhs, rhs));
-
   /* Create the NONLOCAL variable, used to represent the set of nonlocal
      memory.  */
-  nonlocal_tree = create_tmp_var_raw (void_type_node, "NONLOCAL");
+  nonlocal_tree = create_tmp_var_raw (ptr_type_node, "NONLOCAL");
   var_nonlocal = new_var_info (nonlocal_tree, nonlocal_id, "NONLOCAL");
   insert_vi_for_tree (nonlocal_tree, var_nonlocal);
   var_nonlocal->is_artificial_var = 1;
@@ -5234,19 +5193,53 @@ init_base_vars (void)
   var_nonlocal->is_special_var = 1;
   VEC_safe_push (varinfo_t, heap, varmap, var_nonlocal);
 
-  /* Nonlocal memory points to escaped (which includes nonlocal),
-     in order to make deref easier.  */
+  /* ESCAPED = *ESCAPED, because escaped is may-deref'd at calls, etc.  */
+  lhs.type = SCALAR;
+  lhs.var = escaped_id;
+  lhs.offset = 0;
+  rhs.type = DEREF;
+  rhs.var = escaped_id;
+  rhs.offset = 0;
+  process_constraint (new_constraint (lhs, rhs));
+
+  /* ESCAPED = ESCAPED + UNKNOWN_OFFSET, because if a sub-field escapes the
+     whole variable escapes.  */
+  lhs.type = SCALAR;
+  lhs.var = escaped_id;
+  lhs.offset = 0;
+  rhs.type = SCALAR;
+  rhs.var = escaped_id;
+  rhs.offset = UNKNOWN_OFFSET;
+  process_constraint (new_constraint (lhs, rhs));
+
+  /* *ESCAPED = NONLOCAL.  This is true because we have to assume
+     everything pointed to by escaped points to what global memory can
+     point to.  */
+  lhs.type = DEREF;
+  lhs.var = escaped_id;
+  lhs.offset = 0;
+  rhs.type = SCALAR;
+  rhs.var = nonlocal_id;
+  rhs.offset = 0;
+  process_constraint (new_constraint (lhs, rhs));
+
+  /* NONLOCAL = &NONLOCAL, NONLOCAL = &ESCAPED.  This is true because
+     global memory may point to global memory and escaped memory.  */
   lhs.type = SCALAR;
   lhs.var = nonlocal_id;
   lhs.offset = 0;
   rhs.type = ADDRESSOF;
+  rhs.var = nonlocal_id;
+  rhs.offset = 0;
+  process_constraint (new_constraint (lhs, rhs));
+  rhs.type = ADDRESSOF;
   rhs.var = escaped_id;
   rhs.offset = 0;
   process_constraint (new_constraint (lhs, rhs));
 
   /* Create the CALLUSED variable, used to represent the set of call-used
      memory.  */
-  callused_tree = create_tmp_var_raw (void_type_node, "CALLUSED");
+  callused_tree = create_tmp_var_raw (ptr_type_node, "CALLUSED");
   var_callused = new_var_info (callused_tree, callused_id, "CALLUSED");
   insert_vi_for_tree (callused_tree, var_callused);
   var_callused->is_artificial_var = 1;
@@ -5265,6 +5258,16 @@ init_base_vars (void)
   rhs.offset = 0;
   process_constraint (new_constraint (lhs, rhs));
 
+  /* CALLUSED = CALLUSED + UNKNOWN, because if a sub-field is call-used the
+     whole variable is call-used.  */
+  lhs.type = SCALAR;
+  lhs.var = callused_id;
+  lhs.offset = 0;
+  rhs.type = SCALAR;
+  rhs.var = callused_id;
+  rhs.offset = UNKNOWN_OFFSET;
+  process_constraint (new_constraint (lhs, rhs));
+
   /* Create the STOREDANYTHING variable, used to represent the set of
      variables stored to *ANYTHING.  */
   storedanything_tree = create_tmp_var_raw (ptr_type_node, "STOREDANYTHING");
@@ -5279,8 +5282,8 @@ init_base_vars (void)
   VEC_safe_push (varinfo_t, heap, varmap, var_storedanything);
 
   /* Create the INTEGER variable, used to represent that a variable points
-     to an INTEGER.  */
-  integer_tree = create_tmp_var_raw (void_type_node, "INTEGER");
+     to what an INTEGER "points to".  */
+  integer_tree = create_tmp_var_raw (ptr_type_node, "INTEGER");
   var_integer = new_var_info (integer_tree, integer_id, "INTEGER");
   insert_vi_for_tree (integer_tree, var_integer);
   var_integer->is_artificial_var = 1;
@@ -5300,26 +5303,6 @@ init_base_vars (void)
   rhs.var = anything_id;
   rhs.offset = 0;
   process_constraint (new_constraint (lhs, rhs));
-
-  /* *ESCAPED = &ESCAPED.  This is true because we have to assume
-     everything pointed to by escaped can also point to escaped. */
-  lhs.type = DEREF;
-  lhs.var = escaped_id;
-  lhs.offset = 0;
-  rhs.type = ADDRESSOF;
-  rhs.var = escaped_id;
-  rhs.offset = 0;
-  process_constraint (new_constraint (lhs, rhs));
-
-  /* *ESCAPED = &NONLOCAL.  This is true because we have to assume
-     everything pointed to by escaped can also point to nonlocal. */
-  lhs.type = DEREF;
-  lhs.var = escaped_id;
-  lhs.offset = 0;
-  rhs.type = ADDRESSOF;
-  rhs.var = nonlocal_id;
-  rhs.offset = 0;
-  process_constraint (new_constraint (lhs, rhs));
 }
 
 /* Initialize things necessary to perform PTA */
@@ -5516,14 +5499,36 @@ compute_tbaa_pruning (void)
     }
 }
 
+/* Initialize the heapvar for statement mapping.  */
+
+static void
+init_alias_heapvars (void)
+{
+  if (!heapvar_for_stmt)
+    heapvar_for_stmt = htab_create_ggc (11, tree_map_hash, tree_map_eq,
+                                       NULL);
+}
+
+/* Delete the heapvar for statement mapping.  */
+
+void
+delete_alias_heapvars (void)
+{
+  if (heapvar_for_stmt)
+    htab_delete (heapvar_for_stmt);
+  heapvar_for_stmt = NULL;
+}
+
 /* Create points-to sets for the current function.  See the comments
    at the start of the file for an algorithmic overview.  */
 
-void
+static void
 compute_points_to_sets (void)
 {
   struct scc_info *si;
   basic_block bb;
+  unsigned i;
+  sbitmap dereferenced_ptrs;
 
   timevar_push (TV_TREE_PTA);
 
@@ -5532,6 +5537,11 @@ compute_points_to_sets (void)
 
   intra_create_variable_infos ();
 
+  /* A bitmap of SSA_NAME pointers that are dereferenced.  This is
+     used to track which points-to sets may be TBAA pruned.  */
+  dereferenced_ptrs = sbitmap_alloc (num_ssa_names);
+  sbitmap_zero (dereferenced_ptrs);
+
   /* Now walk all statements and derive aliases.  */
   FOR_EACH_BB (bb)
     {
@@ -5546,7 +5556,30 @@ compute_points_to_sets (void)
        }
 
       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
-       find_func_aliases (gsi_stmt (gsi));
+       {
+         gimple stmt = gsi_stmt (gsi);
+         use_operand_p use_p;
+         ssa_op_iter iter;
+
+         /* Mark dereferenced pointers.  This is used by TBAA pruning
+            of the points-to sets and the alias warning machinery.  */
+         FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
+           {
+             unsigned num_uses, num_loads, num_stores;
+             tree op = USE_FROM_PTR (use_p);
+
+             if (!POINTER_TYPE_P (TREE_TYPE (op)))
+               continue;
+
+             /* Determine whether OP is a dereferenced pointer.  */
+             count_uses_and_derefs (op, stmt,
+                                    &num_uses, &num_loads, &num_stores);
+             if (num_loads + num_stores > 0)
+               SET_BIT (dereferenced_ptrs, SSA_NAME_VERSION (op));
+           }
+
+         find_func_aliases (stmt);
+       }
     }
 
 
@@ -5608,15 +5641,35 @@ compute_points_to_sets (void)
   if (dump_file)
     dump_sa_points_to_info (dump_file);
 
-  have_alias_info = true;
+  /* Compute the points-to sets for ESCAPED and CALLUSED used for
+     call-clobber analysis.  */
+  find_what_var_points_to (var_escaped, &cfun->gimple_df->escaped, false);
+  find_what_var_points_to (var_callused, &cfun->gimple_df->callused, false);
+
+  /* Make sure the ESCAPED solution (which is used as placeholder in
+     other solutions) does not reference itself.  This simplifies
+     points-to solution queries.  */
+  cfun->gimple_df->escaped.escaped = 0;
+
+  /* Compute the points-to sets for pointer SSA_NAMEs.  */
+  for (i = 0; i < num_ssa_names; ++i)
+    {
+      tree ptr = ssa_name (i);
+      if (ptr
+         && POINTER_TYPE_P (TREE_TYPE (ptr)))
+       find_what_p_points_to (ptr, TEST_BIT (dereferenced_ptrs, i));
+    }
+  sbitmap_free (dereferenced_ptrs);
 
   timevar_pop (TV_TREE_PTA);
+
+  have_alias_info = true;
 }
 
 
 /* Delete created points-to sets.  */
 
-void
+static void
 delete_points_to_sets (void)
 {
   unsigned int i;
@@ -5647,6 +5700,61 @@ delete_points_to_sets (void)
   have_alias_info = false;
 }
 
+
+/* Compute points-to information for every SSA_NAME pointer in the
+   current function and compute the transitive closure of escaped
+   variables to re-initialize the call-clobber states of local variables.  */
+
+unsigned int
+compute_may_aliases (void)
+{
+  /* For each pointer P_i, determine the sets of variables that P_i may
+     point-to.  Compute the reachability set of escaped and call-used
+     variables.  */
+  compute_points_to_sets ();
+
+  /* Debugging dumps.  */
+  if (dump_file)
+    {
+      dump_alias_info (dump_file);
+
+      if (dump_flags & TDF_DETAILS)
+       dump_referenced_vars (dump_file);
+    }
+
+  /* Deallocate memory used by aliasing data structures and the internal
+     points-to solution.  */
+  delete_points_to_sets ();
+
+  gcc_assert (!need_ssa_update_p (cfun));
+
+  return 0;
+}
+
+
+/* A dummy pass to cause points-to information to be computed via
+   TODO_rebuild_alias.  */
+
+struct gimple_opt_pass pass_build_alias =
+{
+ {
+  GIMPLE_PASS,
+  "alias",                 /* name */
+  NULL,                            /* gate */
+  NULL,                     /* execute */
+  NULL,                     /* sub */
+  NULL,                     /* next */
+  0,                        /* static_pass_number */
+  0,                        /* tv_id */
+  PROP_cfg | PROP_ssa,      /* properties_required */
+  PROP_alias,               /* properties_provided */
+  0,                        /* properties_destroyed */
+  0,                        /* todo_flags_start */
+  TODO_rebuild_alias | TODO_dump_func  /* todo_flags_finish */
+ }
+};
+
+
 /* Return true if we should execute IPA PTA.  */
 static bool
 gate_ipa_pta (void)
@@ -5778,20 +5886,5 @@ struct simple_ipa_opt_pass pass_ipa_pta =
  }
 };
 
-/* Initialize the heapvar for statement mapping.  */
-void
-init_alias_heapvars (void)
-{
-  if (!heapvar_for_stmt)
-    heapvar_for_stmt = htab_create_ggc (11, tree_map_hash, tree_map_eq,
-                                       NULL);
-}
-
-void
-delete_alias_heapvars (void)
-{
-  htab_delete (heapvar_for_stmt);
-  heapvar_for_stmt = NULL;
-}
 
 #include "gt-tree-ssa-structalias.h"
diff --git a/gcc/tree-ssa-structalias.h b/gcc/tree-ssa-structalias.h
deleted file mode 100644 (file)
index 6f2b93d..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/* Tree based points-to analysis
-   Copyright (C) 2002, 2003, 2007, 2008 Free Software Foundation, Inc.
-   Contributed by Daniel Berlin <dberlin@dberlin.org>
-
-   This file is part of GCC.
-
-   GCC is free software; you can redistribute it and/or modify
-   under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, 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 COPYING3.  If not see
-   <http://www.gnu.org/licenses/>.  */
-
-#ifndef TREE_SSA_STRUCTALIAS_H
-#define TREE_SSA_STRUCTALIAS_H
-
-struct constraint;
-typedef struct constraint *constraint_t;
-
-/* In tree-ssa-alias.c.  */
-enum escape_type is_escape_site (gimple);
-void update_mem_sym_stats_from_stmt (tree, gimple, long, long);
-
-/* In tree-ssa-structalias.c.  */
-extern void compute_points_to_sets (void);
-extern void delete_points_to_sets (void);
-extern void dump_constraint (FILE *, constraint_t);
-extern void dump_constraint_edge (FILE *, constraint_t);
-extern void dump_constraints (FILE *);
-extern void dump_constraint_graph (FILE *);
-extern void debug_constraint (constraint_t);
-extern void debug_constraints (void);
-extern void debug_constraint_graph (void);
-extern void dump_solution_for_var (FILE *, unsigned int);
-extern void debug_solution_for_var (unsigned int);
-extern void dump_sa_points_to_info (FILE *);
-extern void debug_sa_points_to_info (void);
-
-#endif /* TREE_SSA_STRUCTALIAS_H  */
index cb393fb..b415971 100644 (file)
@@ -412,7 +412,7 @@ is_replaceable_p (gimple stmt)
     return false;
 
   /* There must be no VDEFs.  */
-  if (!(ZERO_SSA_OPERANDS (stmt, SSA_OP_VDEF)))
+  if (gimple_vdef (stmt))
     return false;
 
   /* Without alias info we can't move around loads.  */
@@ -504,7 +504,7 @@ process_replaceable (temp_expr_table_p tab, gimple stmt)
   tab->expr_decl_uids[version] = def_vars;
 
   /* If there are VUSES, add a dependence on virtual defs.  */
-  if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_VUSE))
+  if (gimple_vuse (stmt))
     {
       make_dependent_on_partition (tab, version, VIRTUAL_PARTITION (tab));
       add_to_partition_kill_list (tab, VIRTUAL_PARTITION (tab), version);
@@ -639,7 +639,7 @@ find_replaceable_in_bb (temp_expr_table_p tab, basic_block bb)
 
       /* A V_{MAY,MUST}_DEF kills any expression using a virtual operand,
         including the current stmt.  */
-      if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_DEFS))
+      if (gimple_vdef (stmt))
         kill_virtual_exprs (tab);
     }
 }
index ee3df24..3c4fc0c 100644 (file)
@@ -271,6 +271,12 @@ verify_ssa_name (tree ssa_name, bool is_virtual)
       return true;
     }
 
+  if (is_virtual && SSA_NAME_VAR (ssa_name) != gimple_vop (cfun))
+    {
+      error ("virtual SSA name for non-VOP decl");
+      return true;
+    }
+
   if (!is_virtual && !is_gimple_reg (ssa_name))
     {
       error ("found a real definition for a non-register");
@@ -520,232 +526,6 @@ error:
 }
 
 
-static void
-verify_flow_insensitive_alias_info (void)
-{
-  tree var;
-  referenced_var_iterator rvi;
-
-  FOR_EACH_REFERENCED_VAR (var, rvi)
-    {
-      unsigned int j;
-      bitmap aliases;
-      tree alias;
-      bitmap_iterator bi;
-
-      if (!MTAG_P (var) || !MTAG_ALIASES (var))
-       continue;
-      
-      aliases = MTAG_ALIASES (var);
-
-      EXECUTE_IF_SET_IN_BITMAP (aliases, 0, j, bi)
-       {
-         alias = referenced_var (j);
-
-         if (TREE_CODE (alias) != MEMORY_PARTITION_TAG
-             && !may_be_aliased (alias))
-           {
-             error ("non-addressable variable inside an alias set");
-             debug_variable (alias);
-             goto err;
-           }
-       }
-    }
-
-  return;
-
-err:
-  debug_variable (var);
-  internal_error ("verify_flow_insensitive_alias_info failed");
-}
-
-
-static void
-verify_flow_sensitive_alias_info (void)
-{
-  size_t i;
-  tree ptr;
-
-  for (i = 1; i < num_ssa_names; i++)
-    {
-      tree var;
-      var_ann_t ann;
-      struct ptr_info_def *pi;
-
-      ptr = ssa_name (i);
-      if (!ptr)
-       continue;
-
-      /* We only care for pointers that are actually referenced in the
-        program.  */
-      if (!POINTER_TYPE_P (TREE_TYPE (ptr)) || !TREE_VISITED (ptr))
-       continue;
-
-      /* RESULT_DECL is special.  If it's a GIMPLE register, then it
-        is only written-to only once in the return statement.
-        Otherwise, aggregate RESULT_DECLs may be written-to more than
-        once in virtual operands.  */
-      var = SSA_NAME_VAR (ptr);
-      if (TREE_CODE (var) == RESULT_DECL
-         && is_gimple_reg (ptr))
-       continue;
-
-      pi = SSA_NAME_PTR_INFO (ptr);
-      if (pi == NULL)
-       continue;
-
-      ann = var_ann (var);
-      if (pi->memory_tag_needed && !pi->name_mem_tag && !ann->symbol_mem_tag)
-       {
-         error ("dereferenced pointers should have a name or a symbol tag");
-         goto err;
-       }
-
-      if (pi->name_mem_tag
-         && (pi->pt_vars == NULL || bitmap_empty_p (pi->pt_vars)))
-       {
-         error ("pointers with a memory tag, should have points-to sets");
-         goto err;
-       }
-
-      if (pi->value_escapes_p
-         && pi->escape_mask & ~ESCAPE_TO_RETURN
-         && pi->name_mem_tag)
-       {
-         tree t = memory_partition (pi->name_mem_tag);
-         if (t == NULL_TREE)
-           t = pi->name_mem_tag;
-         
-         if (!is_call_clobbered (t))
-           {
-             error ("pointer escapes but its name tag is not call-clobbered");
-             goto err;
-           }
-       }
-    }
-
-  return;
-
-err:
-  debug_variable (ptr);
-  internal_error ("verify_flow_sensitive_alias_info failed");
-}
-
-
-/* Verify the consistency of call clobbering information.  */
-
-static void
-verify_call_clobbering (void)
-{
-  unsigned int i;
-  bitmap_iterator bi;
-  tree var;
-  referenced_var_iterator rvi;
-
-  /* At all times, the result of the call_clobbered flag should
-     match the result of the call_clobbered_vars bitmap.  Verify both
-     that everything in call_clobbered_vars is marked
-     call_clobbered, and that everything marked
-     call_clobbered is in call_clobbered_vars.  */
-  EXECUTE_IF_SET_IN_BITMAP (gimple_call_clobbered_vars (cfun), 0, i, bi)
-    {
-      var = referenced_var (i);
-
-      if (memory_partition (var))
-       var = memory_partition (var);
-
-      if (!MTAG_P (var) && !var_ann (var)->call_clobbered)
-       {
-         error ("variable in call_clobbered_vars but not marked "
-                "call_clobbered");
-         debug_variable (var);
-         goto err;
-       }
-    }
-
-  FOR_EACH_REFERENCED_VAR (var, rvi)
-    {
-      if (is_gimple_reg (var))
-       continue;
-
-      if (memory_partition (var))
-       var = memory_partition (var);
-
-      if (!MTAG_P (var)
-         && var_ann (var)->call_clobbered
-         && !bitmap_bit_p (gimple_call_clobbered_vars (cfun), DECL_UID (var)))
-       {
-         error ("variable marked call_clobbered but not in "
-                "call_clobbered_vars bitmap.");
-         debug_variable (var);
-         goto err;
-       }
-    }
-
-  return;
-
- err:
-    internal_error ("verify_call_clobbering failed");
-}
-
-
-/* Verify invariants in memory partitions.  */
-
-static void
-verify_memory_partitions (void)
-{
-  unsigned i;
-  tree mpt;
-  VEC(tree,heap) *mpt_table = gimple_ssa_operands (cfun)->mpt_table;
-  struct pointer_set_t *partitioned_syms = pointer_set_create ();
-
-  for (i = 0; VEC_iterate (tree, mpt_table, i, mpt); i++)
-    {
-      unsigned j;
-      bitmap_iterator bj;
-
-      if (MPT_SYMBOLS (mpt) == NULL)
-       {
-         error ("Memory partitions should have at least one symbol");
-         debug_variable (mpt);
-         goto err;
-       }
-
-      EXECUTE_IF_SET_IN_BITMAP (MPT_SYMBOLS (mpt), 0, j, bj)
-       {
-         tree var = referenced_var (j);
-         if (pointer_set_insert (partitioned_syms, var))
-           {
-             error ("Partitioned symbols should belong to exactly one "
-                    "partition");
-             debug_variable (var);
-             goto err;
-           }
-       }
-    }
-
-  pointer_set_destroy (partitioned_syms);
-
-  return;
-
-err:
-  internal_error ("verify_memory_partitions failed");
-}
-
-
-/* Verify the consistency of aliasing information.  */
-
-static void
-verify_alias_info (void)
-{
-  verify_flow_sensitive_alias_info ();
-  verify_call_clobbering ();
-  verify_flow_insensitive_alias_info ();
-  verify_memory_partitions ();
-}
-
-
 /* Verify common invariants in the SSA web.
    TODO: verify the variable annotations.  */
 
@@ -760,7 +540,7 @@ verify_ssa (bool check_modified_stmt)
   enum dom_state orig_dom_state = dom_info_state (CDI_DOMINATORS);
   bitmap names_defined_in_bb = BITMAP_ALLOC (NULL);
 
-  gcc_assert (!need_ssa_update_p ());
+  gcc_assert (!need_ssa_update_p (cfun));
 
   verify_stmts ();
 
@@ -824,6 +604,7 @@ verify_ssa (bool check_modified_stmt)
        {
          gimple stmt = gsi_stmt (gsi);
          use_operand_p use_p;
+         bool has_err;
 
          if (check_modified_stmt && gimple_modified_p (stmt))
            {
@@ -842,10 +623,8 @@ verify_ssa (bool check_modified_stmt)
              base_address = get_base_address (lhs);
 
              if (base_address
-                 && gimple_aliases_computed_p (cfun)
                  && SSA_VAR_P (base_address)
-                 && !gimple_has_volatile_ops (stmt)
-                 && ZERO_SSA_OPERANDS (stmt, SSA_OP_VDEF))
+                 && !gimple_vdef (stmt))
                {
                  error ("statement makes a memory store, but has no VDEFS");
                  print_gimple_stmt (stderr, stmt, 0, TDF_VOPS);
@@ -853,14 +632,42 @@ verify_ssa (bool check_modified_stmt)
                }
            }
 
-         FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_ALL_VIRTUALS)
+         /* Verify the single virtual operand and its constraints.  */
+         has_err = false;
+         if (gimple_vdef (stmt))
            {
-             if (verify_ssa_name (op, true))
+             if (gimple_vdef_op (stmt) == NULL_DEF_OPERAND_P)
                {
-                 error ("in statement");
-                 print_gimple_stmt (stderr, stmt, 0, TDF_VOPS|TDF_MEMSYMS);
-                 goto err;
+                 error ("statement has VDEF operand not in defs list");
+                 has_err = true;
+               }
+             if (!gimple_vuse (stmt))
+               {
+                 error ("statement has VDEF but no VUSE operand");
+                 has_err = true;
                }
+             else if (SSA_NAME_VAR (gimple_vdef (stmt))
+                      != SSA_NAME_VAR (gimple_vuse (stmt)))
+               {
+                 error ("VDEF and VUSE do not use the same symbol");
+                 has_err = true;
+               }
+             has_err |= verify_ssa_name (gimple_vdef (stmt), true);
+           }
+         if (gimple_vuse (stmt))
+           {
+             if  (gimple_vuse_op (stmt) == NULL_USE_OPERAND_P)
+               {
+                 error ("statement has VUSE operand not in uses list");
+                 has_err = true;
+               }
+             has_err |= verify_ssa_name (gimple_vuse (stmt), true);
+           }
+         if (has_err)
+           {
+             error ("in statement");
+             print_gimple_stmt (stderr, stmt, 0, TDF_VOPS|TDF_MEMSYMS);
+             goto err;
            }
 
          FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_USE|SSA_OP_DEF)
@@ -882,16 +689,24 @@ verify_ssa (bool check_modified_stmt)
            }
 
          FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_ALL_DEFS)
-           bitmap_set_bit (names_defined_in_bb, SSA_NAME_VERSION (op));
+           {
+             if (SSA_NAME_DEF_STMT (op) != stmt)
+               {
+                 error ("SSA_NAME_DEF_STMT is wrong");
+                 fprintf (stderr, "Expected definition statement:\n");
+                 print_gimple_stmt (stderr, stmt, 4, TDF_VOPS);
+                 fprintf (stderr, "\nActual definition statement:\n");
+                 print_gimple_stmt (stderr, SSA_NAME_DEF_STMT (op),
+                                    4, TDF_VOPS);
+                 goto err;
+               }
+             bitmap_set_bit (names_defined_in_bb, SSA_NAME_VERSION (op));
+           }
        }
 
       bitmap_clear (names_defined_in_bb);
     }
 
-  /* Finally, verify alias information.  */
-  if (gimple_aliases_computed_p (cfun))
-    verify_alias_info ();
-
   free (definition_block);
 
   /* Restore the dominance information to its prior known state, so
@@ -974,9 +789,8 @@ init_tree_ssa (struct function *fn)
                                                    uid_decl_map_eq, NULL);
   fn->gimple_df->default_defs = htab_create_ggc (20, uid_ssaname_map_hash, 
                                                 uid_ssaname_map_eq, NULL);
-  fn->gimple_df->call_clobbered_vars = BITMAP_GGC_ALLOC ();
-  fn->gimple_df->call_used_vars = BITMAP_GGC_ALLOC ();
-  fn->gimple_df->addressable_vars = BITMAP_GGC_ALLOC ();
+  pt_solution_reset (&fn->gimple_df->escaped);
+  pt_solution_reset (&fn->gimple_df->callused);
   init_ssanames (fn, 0);
   init_phinodes ();
 }
@@ -1024,10 +838,8 @@ delete_tree_ssa (void)
 
          if (gimple_has_mem_ops (stmt))
            {
-             gimple_set_vdef_ops (stmt, NULL);
-             gimple_set_vuse_ops (stmt, NULL);
-             BITMAP_FREE (stmt->gsmem.membase.stores);
-             BITMAP_FREE (stmt->gsmem.membase.loads);
+             gimple_set_vdef (stmt, NULL_TREE);
+             gimple_set_vuse (stmt, NULL_TREE);
            }
 
          gimple_set_modified (stmt, true);
@@ -1038,13 +850,8 @@ delete_tree_ssa (void)
   /* Remove annotations from every referenced local variable.  */
   FOR_EACH_REFERENCED_VAR (var, rvi)
     {
-      if (!MTAG_P (var)
-         && (TREE_STATIC (var) || DECL_EXTERNAL (var)))
-       {
-         var_ann (var)->mpt = NULL_TREE;
-         var_ann (var)->symbol_mem_tag = NULL_TREE;
-         continue;
-       }
+      if (is_global_var (var))
+       continue;
       if (var->base.ann)
         ggc_free (var->base.ann);
       var->base.ann = NULL;
@@ -1059,22 +866,13 @@ delete_tree_ssa (void)
   if (ssa_operands_active ())
     fini_ssa_operands ();
 
-  cfun->gimple_df->global_var = NULL_TREE;
-  
+  delete_alias_heapvars ();
+
   htab_delete (cfun->gimple_df->default_defs);
   cfun->gimple_df->default_defs = NULL;
-  cfun->gimple_df->call_clobbered_vars = NULL;
-  cfun->gimple_df->call_used_vars = NULL;
-  cfun->gimple_df->addressable_vars = NULL;
+  pt_solution_reset (&cfun->gimple_df->escaped);
+  pt_solution_reset (&cfun->gimple_df->callused);
   cfun->gimple_df->modified_noreturn_calls = NULL;
-  if (gimple_aliases_computed_p (cfun))
-    {
-      delete_alias_heapvars ();
-      gcc_assert (!need_ssa_update_p ());
-    }
-  cfun->gimple_df->aliases_computed_p = false;
-  delete_mem_ref_stats (cfun);
-
   cfun->gimple_df = NULL;
 
   /* We no longer need the edge variable maps.  */
@@ -1507,15 +1305,14 @@ warn_uninitialized_var (tree *tp, int *walk_subtrees, void *data_)
        /* If there is not gimple stmt, 
           or alias information has not been computed,
           then we cannot check VUSE ops.  */
-       if (data->stmt == NULL
-            || !gimple_aliases_computed_p (cfun))
+       if (data->stmt == NULL)
          return NULL_TREE;
 
        /* If the load happens as part of a call do not warn about it.  */
        if (is_gimple_call (data->stmt))
          return NULL_TREE;
 
-       vuse = SINGLE_SSA_USE_OPERAND (data->stmt, SSA_OP_VUSE);
+       vuse = gimple_vuse_op (data->stmt);
        if (vuse == NULL_USE_OPERAND_P)
          return NULL_TREE;
 
@@ -1689,8 +1486,8 @@ struct gimple_opt_pass pass_late_warn_uninitialized =
 
 /* Compute TREE_ADDRESSABLE and DECL_GIMPLE_REG_P for local variables.  */
 
-static unsigned int
-execute_update_addresses_taken (void)
+void
+execute_update_addresses_taken (bool do_optimize)
 {
   tree var;
   referenced_var_iterator rvi;
@@ -1698,7 +1495,6 @@ execute_update_addresses_taken (void)
   basic_block bb;
   bitmap addresses_taken = BITMAP_ALLOC (NULL);
   bitmap not_reg_needs = BITMAP_ALLOC (NULL);
-  bitmap vars_updated = BITMAP_ALLOC (NULL);
   bool update_vops = false;
 
   /* Collect into ADDRESSES_TAKEN all variables whose address is taken within
@@ -1747,69 +1543,69 @@ execute_update_addresses_taken (void)
 
   /* When possible, clear ADDRESSABLE bit or set the REGISTER bit
      and mark variable for conversion into SSA.  */
-  FOR_EACH_REFERENCED_VAR (var, rvi)
-    {
-      /* Global Variables, result decls cannot be changed.  */
-      if (is_global_var (var)
-          || TREE_CODE (var) == RESULT_DECL
-         || bitmap_bit_p (addresses_taken, DECL_UID (var)))
-       continue;
-       
-      if (TREE_ADDRESSABLE (var)
-         /* Do not change TREE_ADDRESSABLE if we need to preserve var as
-            a non-register.  Otherwise we are confused and forget to
-            add virtual operands for it.  */
-         && (!is_gimple_reg_type (TREE_TYPE (var))
-             || !bitmap_bit_p (not_reg_needs, DECL_UID (var))))
-       {
-         TREE_ADDRESSABLE (var) = 0;
-         if (is_gimple_reg (var))
+  if (optimize && do_optimize)
+    FOR_EACH_REFERENCED_VAR (var, rvi)
+      {
+       /* Global Variables, result decls cannot be changed.  */
+       if (is_global_var (var)
+           || TREE_CODE (var) == RESULT_DECL
+           || bitmap_bit_p (addresses_taken, DECL_UID (var)))
+         continue;
+
+       if (TREE_ADDRESSABLE (var)
+           /* Do not change TREE_ADDRESSABLE if we need to preserve var as
+              a non-register.  Otherwise we are confused and forget to
+              add virtual operands for it.  */
+           && (!is_gimple_reg_type (TREE_TYPE (var))
+               || !bitmap_bit_p (not_reg_needs, DECL_UID (var))))
+         {
+           TREE_ADDRESSABLE (var) = 0;
+           if (is_gimple_reg (var))
+             mark_sym_for_renaming (var);
+           update_vops = true;
+           if (dump_file)
+             {
+               fprintf (dump_file, "No longer having address taken ");
+               print_generic_expr (dump_file, var, 0);
+               fprintf (dump_file, "\n");
+             }
+         }
+       if (!DECL_GIMPLE_REG_P (var)
+           && !bitmap_bit_p (not_reg_needs, DECL_UID (var))
+           && (TREE_CODE (TREE_TYPE (var)) == COMPLEX_TYPE
+               || TREE_CODE (TREE_TYPE (var)) == VECTOR_TYPE))
+         {
+           DECL_GIMPLE_REG_P (var) = 1;
            mark_sym_for_renaming (var);
-         update_vops = true;
-         bitmap_set_bit (vars_updated, DECL_UID (var));
-         if (dump_file)
-           {
-             fprintf (dump_file, "No longer having address taken ");
-             print_generic_expr (dump_file, var, 0);
-             fprintf (dump_file, "\n");
-           }
-       }
-      if (!DECL_GIMPLE_REG_P (var)
-         && !bitmap_bit_p (not_reg_needs, DECL_UID (var))
-         && (TREE_CODE (TREE_TYPE (var)) == COMPLEX_TYPE
-             || TREE_CODE (TREE_TYPE (var)) == VECTOR_TYPE))
-       {
-         DECL_GIMPLE_REG_P (var) = 1;
-         mark_sym_for_renaming (var);
-         update_vops = true;
-         bitmap_set_bit (vars_updated, DECL_UID (var));
-         if (dump_file)
-           {
-             fprintf (dump_file, "Decl is now a gimple register ");
-             print_generic_expr (dump_file, var, 0);
-             fprintf (dump_file, "\n");
-           }
-       }
+           update_vops = true;
+           if (dump_file)
+             {
+               fprintf (dump_file, "Decl is now a gimple register ");
+               print_generic_expr (dump_file, var, 0);
+               fprintf (dump_file, "\n");
+             }
+         }
       }
 
   /* Operand caches needs to be recomputed for operands referencing the updated
      variables.  */
   if (update_vops)
-    FOR_EACH_BB (bb)
-      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
-       {
-         gimple stmt = gsi_stmt (gsi);
+    {
+      FOR_EACH_BB (bb)
+         for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+           {
+             gimple stmt = gsi_stmt (gsi);
+
+             if (gimple_references_memory_p (stmt))
+               update_stmt (stmt);
+           }
+
+      /* Update SSA form here, we are called as non-pass as well.  */
+      update_ssa (TODO_update_ssa);
+    }
 
-         if ((gimple_loaded_syms (stmt)
-              && bitmap_intersect_p (gimple_loaded_syms (stmt), vars_updated))
-             || (gimple_stored_syms (stmt)
-                 && bitmap_intersect_p (gimple_stored_syms (stmt), vars_updated)))
-           update_stmt (stmt);
-       }
   BITMAP_FREE (not_reg_needs);
   BITMAP_FREE (addresses_taken);
-  BITMAP_FREE (vars_updated);
-  return 0;
 }
 
 struct gimple_opt_pass pass_update_address_taken =
@@ -1818,7 +1614,7 @@ struct gimple_opt_pass pass_update_address_taken =
   GIMPLE_PASS,
   "addressables",                      /* name */
   NULL,                                        /* gate */
-  execute_update_addresses_taken,      /* execute */
+  NULL,                                        /* execute */
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
@@ -1827,6 +1623,7 @@ struct gimple_opt_pass pass_update_address_taken =
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_update_ssa                       /* todo_flags_finish */
+  TODO_update_address_taken
+  | TODO_dump_func                     /* todo_flags_finish */
  }
 };
index f02bbe6..19032d5 100644 (file)
@@ -87,6 +87,8 @@ init_ssanames (struct function *fn, int size)
      least 50 elements reserved in it.  */
   VEC_quick_push (tree, SSANAMES (fn), NULL_TREE);
   FREE_SSANAMES (fn) = NULL;
+
+  SYMS_TO_RENAME (fn) = BITMAP_GGC_ALLOC ();
 }
 
 /* Finalize management of SSA_NAMEs.  */
@@ -268,12 +270,6 @@ duplicate_ssa_name_ptr_info (tree name, struct ptr_info_def *ptr_info)
   new_ptr_info = GGC_NEW (struct ptr_info_def);
   *new_ptr_info = *ptr_info;
 
-  if (ptr_info->pt_vars)
-    {
-      new_ptr_info->pt_vars = BITMAP_GGC_ALLOC ();
-      bitmap_copy (new_ptr_info->pt_vars, ptr_info->pt_vars);
-    }
-
   SSA_NAME_PTR_INFO (name) = new_ptr_info;
 }
 
index 061d6c9..59a7694 100644 (file)
@@ -136,15 +136,11 @@ suitable_for_tail_opt_p (void)
   if (cfun->stdarg)
     return false;
 
-  /* No local variable nor structure field should be call-used.  We
-     ignore any kind of memory tag, as these are not real variables.  */
-
+  /* No local variable nor structure field should be call-used.  */
   FOR_EACH_REFERENCED_VAR (var, rvi)
     {
       if (!is_global_var (var)
-         && !MTAG_P (var)
-         && (gimple_aliases_computed_p (cfun)? is_call_used (var)
-             : TREE_ADDRESSABLE (var)))
+         && is_call_used (var))
        return false;
     }
 
@@ -410,11 +406,9 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
          break;
        }
 
-      /* If the statement has virtual or volatile operands, fail.  */
-      if (!ZERO_SSA_OPERANDS (stmt, (SSA_OP_VUSE | SSA_OP_VIRTUAL_DEFS))
-         || gimple_has_volatile_ops (stmt)
-         || (!gimple_aliases_computed_p (cfun)
-             && gimple_references_memory_p (stmt)))
+      /* If the statement references memory or volatile operands, fail.  */
+      if (gimple_references_memory_p (stmt)
+         || gimple_has_volatile_ops (stmt))
        return;
     }
 
@@ -914,8 +908,10 @@ tree_optimize_tail_calls_1 (bool opt_tailcalls)
 
       if (!phis_constructed)
        {
-         /* Ensure that there is only one predecessor of the block.  */
-         if (!single_pred_p (first))
+         /* Ensure that there is only one predecessor of the block
+            or if there are existing degenerate PHI nodes.  */
+         if (!single_pred_p (first)
+             || !gimple_seq_empty_p (phi_nodes (first)))
            first = split_edge (single_succ_edge (ENTRY_BLOCK_PTR));
 
          /* Copy the args if needed.  */
index b4cabb6..637075c 100644 (file)
@@ -1815,16 +1815,6 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo)
           return false;
         }
 
-      if (!DR_SYMBOL_TAG (dr))
-        {
-          if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS))
-            {
-              fprintf (vect_dump, "not vectorized: no memory tag for ");
-              print_generic_expr (vect_dump, DR_REF (dr), TDF_SLIM);
-            }
-          return false;
-        }
-
       base = unshare_expr (DR_BASE_ADDRESS (dr));
       offset = unshare_expr (DR_OFFSET (dr));
       init = unshare_expr (DR_INIT (dr));
@@ -2186,7 +2176,7 @@ vect_create_addr_base_for_vector_ref (gimple stmt,
 tree
 vect_create_data_ref_ptr (gimple stmt, struct loop *at_loop,
                          tree offset, tree *initial_address, gimple *ptr_incr,
-                         bool only_init, bool *inv_p, tree type)
+                         bool only_init, bool *inv_p)
 {
   tree base_name;
   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
@@ -2197,7 +2187,6 @@ vect_create_data_ref_ptr (gimple stmt, struct loop *at_loop,
   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
   tree vect_ptr_type;
   tree vect_ptr;
-  tree tag;
   tree new_temp;
   gimple vec_stmt;
   gimple_seq new_stmt_list = NULL;
@@ -2245,42 +2234,34 @@ vect_create_data_ref_ptr (gimple stmt, struct loop *at_loop,
     }
 
   /** (1) Create the new vector-pointer variable:  **/
-  if (type)
-    vect_ptr_type = build_pointer_type (type);
-  else
-    vect_ptr_type = build_pointer_type (vectype);
-
-  if (TREE_CODE (DR_BASE_ADDRESS (dr)) == SSA_NAME
-      && TYPE_RESTRICT (TREE_TYPE (DR_BASE_ADDRESS (dr))))
-    vect_ptr_type = build_qualified_type (vect_ptr_type, TYPE_QUAL_RESTRICT);
+  vect_ptr_type = build_pointer_type (vectype);
   vect_ptr = vect_get_new_vect_var (vect_ptr_type, vect_pointer_var,
                                     get_name (base_name));
-  if (TREE_CODE (DR_BASE_ADDRESS (dr)) == SSA_NAME
-      && TYPE_RESTRICT (TREE_TYPE (DR_BASE_ADDRESS (dr))))
+  /* If any of the data-references in the stmt group does not conflict
+     with the created vector data-reference use a ref-all pointer instead.  */
+  if (STMT_VINFO_DR_GROUP_SIZE (stmt_info) > 1)
     {
-      get_alias_set (base_name);
-      DECL_POINTER_ALIAS_SET (vect_ptr)
-       = DECL_POINTER_ALIAS_SET (SSA_NAME_VAR (DR_BASE_ADDRESS (dr)));
+      gimple orig_stmt = STMT_VINFO_DR_GROUP_FIRST_DR (stmt_info);
+      do
+       {
+         tree lhs = gimple_assign_lhs (orig_stmt);
+         if (!alias_sets_conflict_p (get_deref_alias_set (vect_ptr),
+                                     get_alias_set (lhs)))
+           {
+             vect_ptr_type = build_pointer_type_for_mode (vectype,
+                                                          ptr_mode, true);
+             vect_ptr = vect_get_new_vect_var (vect_ptr_type, vect_pointer_var,
+                                               get_name (base_name));
+             break;
+           }
+
+         orig_stmt = STMT_VINFO_DR_GROUP_NEXT_DR (vinfo_for_stmt (orig_stmt));
+       }
+      while (orig_stmt);
     }
 
   add_referenced_var (vect_ptr);
 
-  /** (2) Add aliasing information to the new vector-pointer:
-          (The points-to info (DR_PTR_INFO) may be defined later.)  **/
-  
-  tag = DR_SYMBOL_TAG (dr);
-  gcc_assert (tag);
-
-  /* If tag is a variable (and NOT_A_TAG) than a new symbol memory
-     tag must be created with tag added to its may alias list.  */
-  if (!MTAG_P (tag))
-    new_type_alias (vect_ptr, tag, DR_REF (dr));
-  else
-    {
-      set_symbol_mem_tag (vect_ptr, tag);
-      mark_sym_for_renaming (tag);
-    }
-
   /** Note: If the dataref is in an inner-loop nested in LOOP, and we are
       vectorizing LOOP (i.e. outer-loop vectorization), we need to create two
       def-use update cycles for the pointer: One relative to the outer-loop
@@ -2858,7 +2839,7 @@ vect_setup_realignment (gimple stmt, gimple_stmt_iterator *gsi,
       pe = loop_preheader_edge (loop_for_initial_load);
       vec_dest = vect_create_destination_var (scalar_dest, vectype);
       ptr = vect_create_data_ref_ptr (stmt, loop_for_initial_load, NULL_TREE,
-                                 &init_addr, &inc, true, &inv_p, NULL_TREE);
+                                     &init_addr, &inc, true, &inv_p);
       data_ref = build1 (ALIGN_INDIRECT_REF, vectype, ptr);
       new_stmt = gimple_build_assign (vec_dest, data_ref);
       new_temp = make_ssa_name (vec_dest, new_stmt);
index 22d515f..16a340c 100644 (file)
@@ -841,7 +841,7 @@ slpeel_can_duplicate_loop_p (const struct loop *loop, const_edge e)
   gimple orig_cond = get_loop_exit_condition (loop);
   gimple_stmt_iterator loop_exit_gsi = gsi_last_bb (exit_e->src);
 
-  if (need_ssa_update_p ())
+  if (need_ssa_update_p (cfun))
     return false;
 
   if (loop->inner
index 60478e9..058438d 100644 (file)
@@ -1307,8 +1307,6 @@ vect_create_mask_and_perm (gimple stmt, gimple next_scalar_stmt,
   stmt_vec_info next_stmt_info;
   int i, group_size, stride, dr_chain_size;
   tree first_vec, second_vec, data_ref;
-  tree sym;
-  ssa_op_iter iter;
   VEC (tree, heap) *params = NULL;
 
   /* Create a vector mask.  */
@@ -1346,12 +1344,6 @@ vect_create_mask_and_perm (gimple stmt, gimple next_scalar_stmt,
       data_ref = make_ssa_name (perm_dest, perm_stmt);
       gimple_call_set_lhs (perm_stmt, data_ref);
       vect_finish_stmt_generation (stmt, perm_stmt, gsi);
-      FOR_EACH_SSA_TREE_OPERAND (sym, perm_stmt, iter, SSA_OP_ALL_VIRTUALS)
-        {
-          if (TREE_CODE (sym) == SSA_NAME)
-            sym = SSA_NAME_VAR (sym);
-          mark_sym_for_renaming (sym);
-        }
 
       /* Store the vector statement in NODE.  */ 
       VEC_replace (gimple, SLP_TREE_VEC_STMTS (node), 
index 8efe4d3..26748c9 100644 (file)
@@ -126,7 +126,7 @@ vect_stmt_relevant_p (gimple stmt, loop_vec_info loop_vinfo,
 
   /* changing memory.  */
   if (gimple_code (stmt) != GIMPLE_PHI)
-    if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_DEFS))
+    if (gimple_vdef (stmt))
       {
        if (vect_print_dump_info (REPORT_DETAILS))
          fprintf (vect_dump, "vec_stmt_relevant_p: stmt has vdefs.");
@@ -1270,7 +1270,7 @@ vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt)
       return false;
     }
 
-  gcc_assert (ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS));
+  gcc_assert (!gimple_vuse (stmt));
 
   if (modifier == NARROW)
     ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_out;
@@ -1436,8 +1436,6 @@ vect_gen_widened_results_half (enum tree_code code,
 { 
   gimple new_stmt;
   tree new_temp; 
-  tree sym; 
-  ssa_op_iter iter;
  
   /* Generate half of the widened result:  */ 
   if (code == CALL_EXPR) 
@@ -1463,16 +1461,6 @@ vect_gen_widened_results_half (enum tree_code code,
     } 
   vect_finish_stmt_generation (stmt, new_stmt, gsi);
 
-  if (code == CALL_EXPR)
-    {
-      FOR_EACH_SSA_TREE_OPERAND (sym, new_stmt, iter, SSA_OP_ALL_VIRTUALS)
-        {
-          if (TREE_CODE (sym) == SSA_NAME)
-            sym = SSA_NAME_VAR (sym);
-          mark_sym_for_renaming (sym);
-        }
-    }
-
   return new_stmt;
 }
 
@@ -1637,9 +1625,6 @@ vectorizable_conversion (gimple stmt, gimple_stmt_iterator *gsi,
     case NONE:
       for (j = 0; j < ncopies; j++)
        {
-         tree sym;
-         ssa_op_iter iter;
-
          if (j == 0)
            vect_get_vec_defs (op0, NULL, stmt, &vec_oprnds0, NULL, slp_node); 
          else
@@ -1654,13 +1639,6 @@ vectorizable_conversion (gimple stmt, gimple_stmt_iterator *gsi,
              new_temp = make_ssa_name (vec_dest, new_stmt);
              gimple_call_set_lhs (new_stmt, new_temp);
              vect_finish_stmt_generation (stmt, new_stmt, gsi);
-             FOR_EACH_SSA_TREE_OPERAND (sym, new_stmt, iter, 
-                                        SSA_OP_ALL_VIRTUALS)
-               {
-                 if (TREE_CODE (sym) == SSA_NAME)
-                   sym = SSA_NAME_VAR (sym);
-                 mark_sym_for_renaming (sym);
-               }
              if (slp_node)
                VEC_quick_push (gimple, SLP_TREE_VEC_STMTS (slp_node), new_stmt);
            }
@@ -3071,7 +3049,7 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
                                                 TREE_TYPE (vec_oprnd)));
          dataref_ptr = vect_create_data_ref_ptr (first_stmt, NULL, NULL_TREE, 
                                                  &dummy, &ptr_incr, false, 
-                                                 &inv_p, NULL);
+                                                 &inv_p);
          gcc_assert (!inv_p);
        }
       else 
@@ -3120,6 +3098,10 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
            vec_oprnd = VEC_index (tree, result_chain, i);
 
          data_ref = build_fold_indirect_ref (dataref_ptr);
+         /* If accesses through a pointer to vectype do not alias the original
+            memory reference we have a problem.  This should never happen.  */
+         gcc_assert (alias_sets_conflict_p (get_alias_set (data_ref),
+                     get_alias_set (gimple_assign_lhs (stmt))));
 
          /* Arguments are ready. Create the new vector stmt.  */
          new_stmt = gimple_build_assign (data_ref, vec_oprnd);
@@ -3456,7 +3438,7 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
         dataref_ptr = vect_create_data_ref_ptr (first_stmt,
                                                at_loop, offset, 
                                                &dummy, &ptr_incr, false, 
-                                               &inv_p, NULL_TREE);
+                                               &inv_p);
       else
         dataref_ptr = 
                bump_vector_ptr (dataref_ptr, ptr_incr, gsi, stmt, NULL_TREE);
@@ -3500,9 +3482,9 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
                new_stmt = gimple_build_assign (vec_dest, data_ref);
                new_temp = make_ssa_name (vec_dest, new_stmt);
                gimple_assign_set_lhs (new_stmt, new_temp);
+               gimple_set_vdef (new_stmt, gimple_vdef (stmt));
+               gimple_set_vuse (new_stmt, gimple_vuse (stmt));
                vect_finish_stmt_generation (stmt, new_stmt, gsi);
-               copy_virtual_operands (new_stmt, stmt);
-               mark_symbols_for_renaming (new_stmt);
                msq = new_temp;
 
                bump = size_binop (MULT_EXPR, vs_minus_1,
@@ -3517,6 +3499,10 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
            default:
              gcc_unreachable ();
            }
+         /* If accesses through a pointer to vectype do not alias the original
+            memory reference we have a problem.  This should never happen. */
+         gcc_assert (alias_sets_conflict_p (get_alias_set (data_ref),
+                     get_alias_set (gimple_assign_rhs1 (stmt))));
          vec_dest = vect_create_destination_var (scalar_dest, vectype);
          new_stmt = gimple_build_assign (vec_dest, data_ref);
          new_temp = make_ssa_name (vec_dest, new_stmt);
index 2645ebe..0cf7862 100644 (file)
@@ -757,7 +757,7 @@ extern bool vect_analyze_data_ref_accesses (loop_vec_info);
 extern bool vect_prune_runtime_alias_test_list (loop_vec_info);
 extern bool vect_analyze_data_refs (loop_vec_info);
 extern tree vect_create_data_ref_ptr (gimple, struct loop *, tree, tree *,
-                                      gimple *, bool, bool *, tree);
+                                      gimple *, bool, bool *);
 extern tree bump_vector_ptr (tree, gimple, gimple_stmt_iterator *, gimple, tree);
 extern tree vect_create_destination_var (tree, tree);
 extern bool vect_strided_store_supported (tree);
index 755b117..cceea25 100644 (file)
@@ -5278,7 +5278,7 @@ stmt_interesting_for_vrp (gimple stmt)
          && ((is_gimple_call (stmt)
               && gimple_call_fndecl (stmt) != NULL_TREE
               && DECL_IS_BUILTIN (gimple_call_fndecl (stmt)))
-             || ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS)))
+             || !gimple_vuse (stmt)))
        return true;
     }
   else if (gimple_code (stmt) == GIMPLE_COND
@@ -6097,7 +6097,7 @@ vrp_visit_stmt (gimple stmt, edge *taken_edge_p, tree *output_p)
       if ((is_gimple_call (stmt)
           && gimple_call_fndecl (stmt) != NULL_TREE
           && DECL_IS_BUILTIN (gimple_call_fndecl (stmt)))
-         || ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
+         || !gimple_vuse (stmt))
        return vrp_visit_assignment_or_call (stmt, output_p);
     }
   else if (gimple_code (stmt) == GIMPLE_COND)
index bbc52e7..a66479d 100644 (file)
@@ -320,15 +320,6 @@ init_ttree (void)
   tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_MINIMAL] = 1;
   tree_contains_struct[LABEL_DECL][TS_DECL_MINIMAL] = 1;
   tree_contains_struct[FIELD_DECL][TS_DECL_MINIMAL] = 1;
-  tree_contains_struct[NAME_MEMORY_TAG][TS_DECL_MINIMAL] = 1;
-  tree_contains_struct[SYMBOL_MEMORY_TAG][TS_DECL_MINIMAL] = 1;
-  tree_contains_struct[MEMORY_PARTITION_TAG][TS_DECL_MINIMAL] = 1;
-
-  tree_contains_struct[NAME_MEMORY_TAG][TS_MEMORY_TAG] = 1;
-  tree_contains_struct[SYMBOL_MEMORY_TAG][TS_MEMORY_TAG] = 1;
-  tree_contains_struct[MEMORY_PARTITION_TAG][TS_MEMORY_TAG] = 1;
-
-  tree_contains_struct[MEMORY_PARTITION_TAG][TS_MEMORY_PARTITION_TAG] = 1;
 
   tree_contains_struct[VAR_DECL][TS_DECL_WITH_VIS] = 1;
   tree_contains_struct[FUNCTION_DECL][TS_DECL_WITH_VIS] = 1;
@@ -465,11 +456,6 @@ tree_code_size (enum tree_code code)
            return sizeof (struct tree_type_decl);
          case FUNCTION_DECL:
            return sizeof (struct tree_function_decl);
-         case NAME_MEMORY_TAG:
-         case SYMBOL_MEMORY_TAG:
-           return sizeof (struct tree_memory_tag);
-         case MEMORY_PARTITION_TAG:
-           return sizeof (struct tree_memory_partition_tag);
          default:
            return sizeof (struct tree_decl_non_common);
          }
@@ -2409,10 +2395,6 @@ tree_node_structure (const_tree t)
            return TS_TYPE_DECL;
          case FUNCTION_DECL:
            return TS_FUNCTION_DECL;
-         case SYMBOL_MEMORY_TAG:
-         case NAME_MEMORY_TAG:
-         case MEMORY_PARTITION_TAG:
-           return TS_MEMORY_TAG;
          default:
            return TS_DECL_NON_COMMON;
          }
@@ -3433,9 +3415,8 @@ build5_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
 }
 
 tree
-build7_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
-            tree arg2, tree arg3, tree arg4, tree arg5,
-            tree arg6 MEM_STAT_DECL)
+build6_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
+            tree arg2, tree arg3, tree arg4, tree arg5 MEM_STAT_DECL)
 {
   bool constant, read_only, side_effects;
   tree t;
@@ -3453,7 +3434,6 @@ build7_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
   PROCESS_ARG(3);
   PROCESS_ARG(4);
   PROCESS_ARG(5);
-  PROCESS_ARG(6);
 
   TREE_SIDE_EFFECTS (t) = side_effects;
   TREE_THIS_VOLATILE (t) = 0;
index a8836c9..a4c524e 100644 (file)
@@ -361,12 +361,6 @@ DEFTREECODE (PARM_DECL, "parm_decl", tcc_declaration, 0)
 DEFTREECODE (TYPE_DECL, "type_decl", tcc_declaration, 0)
 DEFTREECODE (RESULT_DECL, "result_decl", tcc_declaration, 0)
 
-/* Memory tags used in tree-ssa to represent memory locations in
-   virtual SSA.  */
-DEFTREECODE (NAME_MEMORY_TAG, "name_memory_tag", tcc_declaration, 0)
-DEFTREECODE (SYMBOL_MEMORY_TAG, "symbol_memory_tag", tcc_declaration, 0)
-DEFTREECODE (MEMORY_PARTITION_TAG, "memory_partition_tag", tcc_declaration, 0)
-
 /* A namespace declaration.  Namespaces appear in DECL_CONTEXT of other
    _DECLs, providing a hierarchy of names.  */
 DEFTREECODE (NAMESPACE_DECL, "namespace_decl", tcc_declaration, 0)
@@ -992,10 +986,9 @@ DEFTREECODE (REALIGN_LOAD_EXPR, "realign_load", tcc_expression, 3)
    sizetype or a pointer type (if SYMBOL is NULL).
    
    The sixth argument is the reference to the original memory access, which
-   is preserved for the purposes of the RTL alias analysis.  The seventh
-   argument is a tag representing results of the tree level alias analysis.  */
+   is preserved for the purposes of the RTL alias analysis.  */
 
-DEFTREECODE (TARGET_MEM_REF, "target_mem_ref", tcc_reference, 7)
+DEFTREECODE (TARGET_MEM_REF, "target_mem_ref", tcc_reference, 6)
 
 /* The ordering of the codes between OMP_PARALLEL and OMP_CRITICAL is
    exposed to TREE_RANGE_CHECK.  */
index 1f262f6..b191d43 100644 (file)
@@ -105,14 +105,6 @@ extern const enum tree_code_class tree_code_type[];
 #define DECL_P(CODE)\
         (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_declaration)
 
-/* Nonzero if CODE represents a memory tag.  */
-
-#define MTAG_P(CODE) \
-  (TREE_CODE (CODE) == NAME_MEMORY_TAG         \
-   || TREE_CODE (CODE) == SYMBOL_MEMORY_TAG    \
-   || TREE_CODE (CODE) == MEMORY_PARTITION_TAG)
-
-
 /* Nonzero if DECL represents a VAR_DECL or FUNCTION_DECL.  */
 
 #define VAR_OR_FUNCTION_DECL_P(DECL)\
@@ -933,7 +925,6 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
 
 #define TYPE_CHECK(T)          TREE_CLASS_CHECK (T, tcc_type)
 #define DECL_MINIMAL_CHECK(T)   CONTAINS_STRUCT_CHECK (T, TS_DECL_MINIMAL)
-#define TREE_MEMORY_TAG_CHECK(T)       CONTAINS_STRUCT_CHECK (T, TS_MEMORY_TAG)
 #define DECL_COMMON_CHECK(T)    CONTAINS_STRUCT_CHECK (T, TS_DECL_COMMON)
 #define DECL_WRTL_CHECK(T)      CONTAINS_STRUCT_CHECK (T, TS_DECL_WRTL)
 #define DECL_WITH_VIS_CHECK(T)  CONTAINS_STRUCT_CHECK (T, TS_DECL_WITH_VIS)
@@ -1613,7 +1604,6 @@ extern void protected_set_expr_location (tree, location_t);
 #define TMR_STEP(NODE) (TREE_OPERAND (TARGET_MEM_REF_CHECK (NODE), 3))
 #define TMR_OFFSET(NODE) (TREE_OPERAND (TARGET_MEM_REF_CHECK (NODE), 4))
 #define TMR_ORIGINAL(NODE) (TREE_OPERAND (TARGET_MEM_REF_CHECK (NODE), 5))
-#define TMR_TAG(NODE) (TREE_OPERAND (TARGET_MEM_REF_CHECK (NODE), 6))
 
 /* The operands of a BIND_EXPR.  */
 #define BIND_EXPR_VARS(NODE) (TREE_OPERAND (BIND_EXPR_CHECK (NODE), 0))
@@ -2438,12 +2428,10 @@ struct tree_binfo GTY (())
        (TREE_CODE (DECL) == VAR_DECL                                   \
         || TREE_CODE (DECL) == PARM_DECL                               \
         || TREE_CODE (DECL) == RESULT_DECL                             \
-        || MTAG_P (DECL)                                               \
         || (TREE_CODE (DECL) == SSA_NAME                               \
             && (TREE_CODE (SSA_NAME_VAR (DECL)) == VAR_DECL            \
                 || TREE_CODE (SSA_NAME_VAR (DECL)) == PARM_DECL        \
-                || TREE_CODE (SSA_NAME_VAR (DECL)) == RESULT_DECL      \
-                || MTAG_P (SSA_NAME_VAR (DECL)))))
+                || TREE_CODE (SSA_NAME_VAR (DECL)) == RESULT_DECL)))
 
 
 
@@ -2498,49 +2486,6 @@ struct tree_decl_minimal GTY(())
   tree context;
 };
 
-/* When computing aliasing information, we represent the memory pointed-to
-   by pointers with artificial variables called "memory tags" (MT).  There
-   are two kinds of tags, namely symbol and name:
-
-   Symbol tags (SMT) are used in flow-insensitive alias analysis, they
-   represent all the pointed-to locations and variables pointed-to by
-   the same pointer symbol.  Usually, this set is computed using
-   type-based analysis (i.e., alias set classes), but this may not
-   always be the case.
-
-   Name tags (NMT) are used in flow-sensitive points-to alias
-   analysis, they represent the variables and memory locations
-   pointed-to by a specific SSA_NAME pointer.
-
-   In general, given a pointer P with a symbol tag SMT, the alias set
-   of SMT should be the union of all the alias sets of the NMTs of
-   every SSA_NAME for P.  */
-struct tree_memory_tag GTY(())
-{
-  struct tree_decl_minimal common;
-
-  bitmap GTY ((skip)) aliases;
-
-  /* True if this tag has global scope.  */
-  unsigned int is_global : 1;
-};
-
-#define MTAG_GLOBAL(NODE) (TREE_MEMORY_TAG_CHECK (NODE)->mtag.is_global)
-#define MTAG_ALIASES(NODE) (TREE_MEMORY_TAG_CHECK (NODE)->mtag.aliases)
-
-/* Memory Partition Tags (MPTs) group memory symbols under one
-   common name for the purposes of placing memory PHI nodes.  */
-
-struct tree_memory_partition_tag GTY(())
-{
-  struct tree_memory_tag common;
-  
-  /* Set of symbols grouped under this MPT.  */
-  bitmap symbols;
-};
-
-#define MPT_SYMBOLS(NODE)      (MEMORY_PARTITION_TAG_CHECK (NODE)->mpt.symbols)
-
 
 /* For any sort of a ..._DECL node, this points to the original (abstract)
    decl node which this decl is an instance of, or else it is NULL indicating
@@ -3448,9 +3393,7 @@ union tree_node GTY ((ptr_alias (union lang_tree_node),
   struct tree_binfo GTY ((tag ("TS_BINFO"))) binfo;
   struct tree_statement_list GTY ((tag ("TS_STATEMENT_LIST"))) stmt_list;
   struct tree_constructor GTY ((tag ("TS_CONSTRUCTOR"))) constructor;
-  struct tree_memory_tag GTY ((tag ("TS_MEMORY_TAG"))) mtag;
   struct tree_omp_clause GTY ((tag ("TS_OMP_CLAUSE"))) omp_clause;
-  struct tree_memory_partition_tag GTY ((tag ("TS_MEMORY_PARTITION_TAG"))) mpt;
   struct tree_optimization_option GTY ((tag ("TS_OPTIMIZATION"))) optimization;
   struct tree_target_option GTY ((tag ("TS_TARGET_OPTION"))) target_option;
 };
@@ -3942,10 +3885,10 @@ extern tree build4_stat (enum tree_code, tree, tree, tree, tree,
 extern tree build5_stat (enum tree_code, tree, tree, tree, tree, tree,
                         tree MEM_STAT_DECL);
 #define build5(c,t1,t2,t3,t4,t5,t6) build5_stat (c,t1,t2,t3,t4,t5,t6 MEM_STAT_INFO)
-extern tree build7_stat (enum tree_code, tree, tree, tree, tree, tree,
-                        tree, tree, tree MEM_STAT_DECL);
-#define build7(c,t1,t2,t3,t4,t5,t6,t7,t8) \
-  build7_stat (c,t1,t2,t3,t4,t5,t6,t7,t8 MEM_STAT_INFO)
+extern tree build6_stat (enum tree_code, tree, tree, tree, tree, tree,
+                        tree, tree MEM_STAT_DECL);
+#define build6(c,t1,t2,t3,t4,t5,t6,t7) \
+  build6_stat (c,t1,t2,t3,t4,t5,t6,t7 MEM_STAT_INFO)
 
 extern tree build_int_cst (tree, HOST_WIDE_INT);
 extern tree build_int_cst_type (tree, HOST_WIDE_INT);
index dc3e287..e920a97 100644 (file)
@@ -60,9 +60,7 @@ DEFTREESTRUCT(TS_BINFO, "binfo")
 DEFTREESTRUCT(TS_STATEMENT_LIST, "statement list")
 DEFTREESTRUCT(TS_GIMPLE_STATEMENT, "gimple statement")
 DEFTREESTRUCT(TS_CONSTRUCTOR, "constructor")
-DEFTREESTRUCT(TS_MEMORY_TAG, "memory tag")
 DEFTREESTRUCT(TS_OMP_CLAUSE, "omp clause")
-DEFTREESTRUCT(TS_MEMORY_PARTITION_TAG, "memory partition tag")
 DEFTREESTRUCT(TS_OPTIMIZATION, "optimization options")
 DEFTREESTRUCT(TS_TARGET_OPTION, "target options")