This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC] [alias, middle-end] Alias and data dependency export


Hello,

The attached patch implements (again) the exporting of alias and data dependency information from Tree SSA and reusing it on RTL level. Looking back, I can tell that the previous attempt on this was quite good, as it solved all problems I had to solve with the current patch, but it was also too early to produce interesting results without Richard's alias improvements and oracle (thank you Richard!). Also, the patch was much easier to complete after Michael's expand from SSA went in (thank you Michael!), though it still worked pretty good.

The patch adds MEM_ORIG_EXPR field to mem_attrs, which is initialized to a complete tree that was used to generate this mem from. The MEM_EXPR field is retained for the sake of existing code, if there's any cleanups possible here, I can work on this as a followup. For alias export, MEM_ORIG_EXPR is then basically passed to the refs_may_alias_p oracle, together with saved points-to information where applicable, when answering queries from alias.c functions. For data dependency export, MEM_ORIG_EXPR is used as a key for accessing saved data references and dependence relations, and this is also used for alias.c and for modulo scheduling.

When gathering information for export, we need to rebuild aliasing for alias export and to schedule an extra pass for computing data dependency info for ddg export. The MEM_ORIG_EXPR field is initialized when memory attributes are computed in set_mem_attributes_minus_bitpos, it is also unshared so we can release trees coming into that function. The points-to sets are also recorded during that time.

The alias oracle is a bit modified so that it allows for points-to sets and escaped solution to come from outside. The current implementation for this is quite ugly (macros), but it worked, avoided code duplication, and made merges easier for me. I'm happy to do here whatever Richi would suggest.

The interesting part of alias export is accounting for stack slot sharing info. We need to make sure that all points-to sets that have some of stack partition variables set get all of them set, that all partitioned pointers have their points-to sets unified, and that all bases are rewritten to their stack partition representative. Also, TREE_ADDRESSABLE bit should be propagated within a partition. Hopefully, I got it right after fixing all test suite failures :-)

The interesting part of ddg export is that, first, array accesses with non-zero distances are used for disambiguation for everything except passes that do pipelining (modulo-sched, sel-sched), and this doesn't happen after pipelining, as the information might become incorrect. Second, the information also becomes wrong after unrolling, so it is removed from insns of the new copy of the unrolled loop.

The patch bootstraps/regtests on x86-64 with all default languages and ada, producing about 800K new disambiguations for SPEC2k on x86-64. The number of new disambiguations is reported via statistics infrastructure. Performance-wise, the patch is a steady win on ia64 last time I checked (~3% on SPEC2k FP with -O3, 634 vs 616, neutral on SPEC2k Int), and it had some ups and downs on SPEC2k6 x86-64 when Richi tested it last time, overall slightly positive (probably, I haven't seen the logs). If somebody can help with performance testing on other architectures, that would be great. We have SPEC2k6 sources now, so I can take a look on performance issues.

Also, there are some points on which I'd like an advice:

- I'm freeing the information from pass_clean_state, is this fine or do we want a general pass that frees on the side stuff like this and df?

- Are there any places that should be adding/removing MEM_ORIG_EXPRs except the ones I've fixed? While writing the patch, we had a checking pass for that, which attributed each missing MEM_ORIG_EXPR to be fine wrt its usefulness (e.g., SYMBOL_REFs, byproducts of expanding calls, tablejumps, BLKmode mems, etc -- tree aliasing doesn't know about those anyways);

- the fix in discover_nonconstant_array_refs_r that limits setting of TREE_ADDRESSABLE to BLKmode arrays was suggested by Richard and can be submitted separately; I don't know anything about it except that it works;

- the fix for statistics.s can be also submitted separately;

- the flags for alias/ddg export should probably be gone if the patch is accepted for trunk.

Thoughts, comments? OK for trunk?

Andrey

2009-05-13  Andrey Belevantsev  <abel@ispras.ru>
	    Dmitry Melnik  <dm@ispras.ru>
	    Alexander Monakov  <amonakov@ispras.ru>
	    Dmitry Zhurikhin  <zhur@ispras.ru>
	
	Alias and data dependency export.

	* Makefile.in (OBJS-common): Add alias-export.o.
	(tree-ssa.o): Depend on alias-export.h.
	(tree-ssa-loop-ivopts.o): Likewise.
	(tree-ssa-alias.o): Likewise.
	(emit-rtl.o): Likewise.
	(loop-unroll.o): Likewise.
	(alias.o): Likewise.
	(modulo-sched.o): Likewise.
	(sel-sched.o): Likewise.
	(final.o): Likewise.
	* alias-export.c: New file.
	* alias-export.h: New file.
	* rtl.h (struct mem_attrs): New field orig_expr.
	(MEM_ORIG_EXPR): New access macro.
	* tree-ssa-uncprop.c (pass_uncprop): Set TODO_rebuild_alias.
	* tree-ssa.c: Include alias-export.h.
	(delete_tree_ssa): Only release ssa names when not exporting info.
	Record escaped solution for alias export.
	* tree-ssa-loop-ivopts.c: Include alias-export.h.
	(copy_ref_info): Record new reference in ddg export data.
	* tree-ssa-alias.c: Include alias-export.h.
	(GET_PTR_INFO_FOR, GET_ESCAPED_SOLUTION): New macros.
	(ptr_deref_may_alias_decl_p): Add expi and exescaped parameters.
	Use them to access PTA data.  Adjust assert to include RTL case.
	(ptr_derefs_may_alias_p): Add expi1, expi2, exescaped parameters.
	Use them to access PTA data.  Adjust assert to include RTL case.
	(indirect_ref_may_alias_decl_p): Add expi1 and exescaped parameters.
	Use them to access PTA data.
	(indirect_refs_may_alias_p): Add expi1, expi2, exesaped parameters.
	Use them to access PTA data.
	(refs_may_alias_p_1): Likewise.  Adjust assert to include RTL case.
	* tree-ssa-alias.h (refs_may_alias_p_1, pt_solution_includes_1,
	pt_solutions_intersect_1): Export.
	* tree-ssa-structalias.c (pt_solution_includes_1,
	pt_solutions_intersect_1): Add escaped parameter, make global.
	* cfgexpand.c: Include alias-export.h.
	(union_stack_vars): Promote TREE_ADDRESSABLE to the merged partition
	representative.
	(record_stack_var_partitions): New.
	(expand_used_vars): Call it.
	(discover_nonconstant_array_refs_r): Make only BLKmode arrays addressable.
	(gimple_expand_cfg): Also set MEM_ORIG_EXPR to NULL.
	* expr.c (expand_expr_real_1): When expanding TARGET_MEM_REF,
	set MEM_ORIG_EXPR to its TMR_ORIGINAL.
	* function.c (assign_parms_unsplit_complex): Also set MEM_ORIG_EXPR
	for parm.
	* emit-rtl.c: Include alias-export.h.
	(mem_attrs_htab_hash, get_mem_attrs, set_mem_attrs_from_reg,
	set_mem_alias_set, set_mem_align, set_mem_expr, set_mem_offset,
	set_mem_size, change_address, offset_address,
	widen_memory_access, get_spill_slot_decl,
	set_mem_attrs_for_spill): Account for MEM_ORIG_EXPR.
	(set_mem_orig_expr): New.
	(set_mem_attributes_minus_bitpos): Record MEM_ORIG_EXPR.
	(adjust_address_1): When we make a wider address, nullify MEM_ORIG_EXPR.
	* emit-rtl.h (set_mem_orig_expr): Export.
	* final.c: Include alias-export.h.
	(rest_of_clean_state): Free exported information.
	* alias.c: Include alias-export.h.
	(query_alias_export_info): New.
	(walk_mems_2): Also query ddg export info.
	(true_dependence): Use query_alias_export_info.
	(canon_true_dependence, write_dependence_p): Likewise.
	* loop-unroll.c: Include alias-export.h.
	(apply_opt_in_copies): Clear exported ddg data on insns in unrolled
	loop.
	* modulo-sched.c: Include alias-export.h.
	(rest_of_handle_sms): Call ddg_export_set_pipelining_completed.
	* sel-sched.c: Include alias-export.h.
	(sel_global_finish): Call ddg_export_set_pipelining_completed.	
	* common.opt (falias-export, fddg-export): New options.
	* dbgcnt.def (alias_export, ddg_export): New counter.
	* tree-pass.h (pass_gather_ddg_info): Export.
	* builtins.c (get_memory_rtx): Also set MEM_ORIG_EXPR to NULL.
	* passes.c (init_optimization_passes): Schedule pass for ddg export.
	* statistics.c (statistics_counter_event): Do not record event in pass
	dump if its number == -1.
	(curr_statistics_hash): Add assert that we never get passes with static
	number == -1.
diff -cprdN -x .svn -x TAGS trunk/gcc/Makefile.in alias-export/gcc/Makefile.in
*** trunk/gcc/Makefile.in	Wed May 13 10:45:32 2009
--- alias-export/gcc/Makefile.in	Wed May 13 11:21:36 2009
*************** OBJS-common = \
*** 1057,1062 ****
--- 1057,1063 ----
  	insn-recog.o \
  	$(GGC) \
  	alias.o \
+ 	alias-export.o \
  	alloc-pool.o \
  	auto-inc-dec.o \
  	bb-reorder.o \
*************** convert.o: convert.c $(CONFIG_H) $(SYSTE
*** 2060,2065 ****
--- 2061,2073 ----
  
  double-int.o: double-int.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H)
  
+ alias-export.o : alias-export.c alias-export.h 	\
+    $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(BASIC_BLOCK_H) \
+    $(FUNCTION_H) $(TREE_DUMP_H) $(TIMEVAR_H) $(GGC_H) output.h $(TREE_FLOW_H) \
+    $(RTL_H) $(TREE_PASS_H) $(FLAGS_H) tree-ssa-alias.h vec.h bitmap.h \
+    pointer-set.h dbgcnt.h $(CFGLOOP_H) tree-data-ref.h tree-scalar-evolution.h \
+    $(DIAGNOSTIC_H) statistics.h
+ 
  langhooks.o : langhooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
     $(TREE_H) $(TOPLEV_H) $(TREE_INLINE_H) $(RTL_H) insn-config.h $(INTEGRATE_H) \
     langhooks.h $(TARGET_H) $(LANGHOOKS_DEF_H) $(FLAGS_H) $(GGC_H) $(DIAGNOSTIC_H) \
*************** tree-ssa.o : tree-ssa.c $(TREE_FLOW_H) $
*** 2097,2103 ****
     $(TOPLEV_H) $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h \
     $(TREE_DUMP_H) langhooks.h $(TREE_PASS_H) $(BASIC_BLOCK_H) $(BITMAP_H) \
     $(FLAGS_H) $(GGC_H) hard-reg-set.h $(HASHTAB_H) pointer-set.h \
!    $(GIMPLE_H) $(TREE_INLINE_H) $(VARRAY_H)
  tree-into-ssa.o : tree-into-ssa.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
     $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) output.h $(DIAGNOSTIC_H) \
     $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
--- 2105,2111 ----
     $(TOPLEV_H) $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h \
     $(TREE_DUMP_H) langhooks.h $(TREE_PASS_H) $(BASIC_BLOCK_H) $(BITMAP_H) \
     $(FLAGS_H) $(GGC_H) hard-reg-set.h $(HASHTAB_H) pointer-set.h \
!    $(GIMPLE_H) $(TREE_INLINE_H) $(VARRAY_H) alias-export.h
  tree-into-ssa.o : tree-into-ssa.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
     $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) output.h $(DIAGNOSTIC_H) \
     $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
*************** tree-ssa-loop-ivopts.o : tree-ssa-loop-i
*** 2289,2295 ****
     output.h $(DIAGNOSTIC_H) $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
     $(TREE_PASS_H) $(GGC_H) $(RECOG_H) insn-config.h $(HASHTAB_H) $(SCEV_H) \
     $(CFGLOOP_H) $(PARAMS_H) langhooks.h $(BASIC_BLOCK_H) hard-reg-set.h \
!    tree-chrec.h $(VARRAY_H) tree-affine.h pointer-set.h $(TARGET_H)
  tree-affine.o : tree-affine.c tree-affine.h $(CONFIG_H) pointer-set.h \
     $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) hard-reg-set.h $(GIMPLE_H) \
     output.h $(DIAGNOSTIC_H) $(TM_H) coretypes.h $(TREE_DUMP_H) $(FLAGS_H)
--- 2297,2303 ----
     output.h $(DIAGNOSTIC_H) $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
     $(TREE_PASS_H) $(GGC_H) $(RECOG_H) insn-config.h $(HASHTAB_H) $(SCEV_H) \
     $(CFGLOOP_H) $(PARAMS_H) langhooks.h $(BASIC_BLOCK_H) hard-reg-set.h \
!    tree-chrec.h $(VARRAY_H) tree-affine.h pointer-set.h $(TARGET_H) alias-export.h
  tree-affine.o : tree-affine.c tree-affine.h $(CONFIG_H) pointer-set.h \
     $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) hard-reg-set.h $(GIMPLE_H) \
     output.h $(DIAGNOSTIC_H) $(TM_H) coretypes.h $(TREE_DUMP_H) $(FLAGS_H)
*************** tree-ssa-alias.o : tree-ssa-alias.c $(TR
*** 2311,2317 ****
     $(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 \
!    $(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) \
     $(TM_H) coretypes.h $(TREE_DUMP_H) $(TREE_PASS_H) $(FLAGS_H) \
--- 2319,2325 ----
     $(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 \
!    $(IPA_TYPE_ESCAPE_H) vecprim.h pointer-set.h alloc-pool.h alias-export.h
  tree-ssa-reassoc.o : tree-ssa-reassoc.c $(TREE_FLOW_H) $(CONFIG_H) \
     $(SYSTEM_H) $(TREE_H) $(GGC_H) $(DIAGNOSTIC_H) $(TIMEVAR_H) \
     $(TM_H) coretypes.h $(TREE_DUMP_H) $(TREE_PASS_H) $(FLAGS_H) \
*************** emit-rtl.o : emit-rtl.c $(CONFIG_H) $(SY
*** 2585,2591 ****
     $(TREE_H) $(FLAGS_H) $(FUNCTION_H) $(REGS_H) insn-config.h $(RECOG_H) \
     $(GGC_H) $(EXPR_H) hard-reg-set.h $(BITMAP_H) $(TOPLEV_H) $(BASIC_BLOCK_H) \
     $(HASHTAB_H) $(TM_P_H) debug.h langhooks.h $(TREE_PASS_H) gt-emit-rtl.h \
!    $(REAL_H) $(DF_H)
  real.o : real.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
     $(TOPLEV_H) $(TM_P_H) $(REAL_H) dfp.h
  dfp.o : dfp.c dfp.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H)	$(TREE_H) \
--- 2593,2599 ----
     $(TREE_H) $(FLAGS_H) $(FUNCTION_H) $(REGS_H) insn-config.h $(RECOG_H) \
     $(GGC_H) $(EXPR_H) hard-reg-set.h $(BITMAP_H) $(TOPLEV_H) $(BASIC_BLOCK_H) \
     $(HASHTAB_H) $(TM_P_H) debug.h langhooks.h $(TREE_PASS_H) gt-emit-rtl.h \
!    $(REAL_H) $(DF_H) alias-export.h pointer-set.h
  real.o : real.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
     $(TOPLEV_H) $(TM_P_H) $(REAL_H) dfp.h
  dfp.o : dfp.c dfp.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H)	$(TREE_H) \
*************** loop-unswitch.o : loop-unswitch.c $(CONF
*** 2857,2863 ****
  loop-unroll.o: loop-unroll.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TM_H) \
     $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(CFGLAYOUT_H) $(PARAMS_H) \
     output.h $(EXPR_H) coretypes.h $(TM_H) $(HASHTAB_H) $(RECOG_H) \
!    $(OBSTACK_H)
  dominance.o : dominance.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
     hard-reg-set.h $(BASIC_BLOCK_H) et-forest.h $(OBSTACK_H) $(TOPLEV_H) \
     $(TIMEVAR_H) graphds.h vecprim.h pointer-set.h
--- 2865,2871 ----
  loop-unroll.o: loop-unroll.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TM_H) \
     $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(CFGLAYOUT_H) $(PARAMS_H) \
     output.h $(EXPR_H) coretypes.h $(TM_H) $(HASHTAB_H) $(RECOG_H) \
!    $(OBSTACK_H) alias-export.h 
  dominance.o : dominance.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
     hard-reg-set.h $(BASIC_BLOCK_H) et-forest.h $(OBSTACK_H) $(TOPLEV_H) \
     $(TIMEVAR_H) graphds.h vecprim.h pointer-set.h
*************** reorg.o : reorg.c $(CONFIG_H) $(SYSTEM_H
*** 2916,2922 ****
  alias.o : alias.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
     $(FLAGS_H) hard-reg-set.h $(BASIC_BLOCK_H) $(REGS_H) $(TOPLEV_H) output.h \
     $(ALIAS_H) $(EMIT_RTL_H) $(GGC_H) $(FUNCTION_H) cselib.h $(TREE_H) $(TM_P_H) \
!    langhooks.h $(TARGET_H) gt-alias.h $(TIMEVAR_H) $(CGRAPH_H) \
     $(SPLAY_TREE_H) $(VARRAY_H) $(IPA_TYPE_ESCAPE_H) $(DF_H) $(TREE_PASS_H)
  stack-ptr-mod.o : stack-ptr-mod.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
     $(TM_H) $(TREE_H) $(RTL_H) $(REGS_H) $(EXPR_H) $(TREE_PASS_H) \
--- 2924,2930 ----
  alias.o : alias.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
     $(FLAGS_H) hard-reg-set.h $(BASIC_BLOCK_H) $(REGS_H) $(TOPLEV_H) output.h \
     $(ALIAS_H) $(EMIT_RTL_H) $(GGC_H) $(FUNCTION_H) cselib.h $(TREE_H) $(TM_P_H) \
!    langhooks.h $(TARGET_H) gt-alias.h $(TIMEVAR_H) $(CGRAPH_H) alias-export.h \
     $(SPLAY_TREE_H) $(VARRAY_H) $(IPA_TYPE_ESCAPE_H) $(DF_H) $(TREE_PASS_H)
  stack-ptr-mod.o : stack-ptr-mod.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
     $(TM_H) $(TREE_H) $(RTL_H) $(REGS_H) $(EXPR_H) $(TREE_PASS_H) \
*************** modulo-sched.o : modulo-sched.c $(DDG_H)
*** 2973,2979 ****
     $(FLAGS_H) insn-config.h $(INSN_ATTR_H) $(EXCEPT_H) $(RECOG_H) \
     $(SCHED_INT_H) $(CFGLAYOUT_H) $(CFGLOOP_H) $(EXPR_H) $(PARAMS_H) \
     cfghooks.h $(GCOV_IO_H) hard-reg-set.h $(TM_H) $(TIMEVAR_H) $(TREE_PASS_H) \
!    $(DF_H) $(DBGCNT_H)
  haifa-sched.o : haifa-sched.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
     $(SCHED_INT_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h $(FUNCTION_H) \
     $(INSN_ATTR_H) $(TOPLEV_H) $(RECOG_H) $(EXCEPT_H) $(TM_P_H) $(TARGET_H) output.h \
--- 2981,2987 ----
     $(FLAGS_H) insn-config.h $(INSN_ATTR_H) $(EXCEPT_H) $(RECOG_H) \
     $(SCHED_INT_H) $(CFGLAYOUT_H) $(CFGLOOP_H) $(EXPR_H) $(PARAMS_H) \
     cfghooks.h $(GCOV_IO_H) hard-reg-set.h $(TM_H) $(TIMEVAR_H) $(TREE_PASS_H) \
!    $(DF_H) $(DBGCNT_H) alias-export.h
  haifa-sched.o : haifa-sched.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
     $(SCHED_INT_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h $(FUNCTION_H) \
     $(INSN_ATTR_H) $(TOPLEV_H) $(RECOG_H) $(EXCEPT_H) $(TM_P_H) $(TARGET_H) output.h \
*************** sel-sched.o : sel-sched.c $(CONFIG_H) $(
*** 2999,3005 ****
     $(FUNCTION_H) $(INSN_ATTR_H) toplev.h $(RECOG_H) $(EXCEPT_H) $(PARAMS_H) \
     $(TM_P_H) $(TARGET_H) $(CFGLAYOUT_H) $(TIMEVAR_H) $(TREE_PASS_H)  \
     $(SCHED_INT_H) $(GGC_H) $(TREE_H) $(LANGHOOKS_DEF_H) \
!    $(SEL_SCHED_IR_H) $(SEL_SCHED_DUMP_H) sel-sched.h
  sel-sched-dump.o : sel-sched-dump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
     $(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
     $(FUNCTION_H) $(INSN_ATTR_H) toplev.h $(RECOG_H) $(EXCEPT_H) $(PARAMS_H) \
--- 3007,3013 ----
     $(FUNCTION_H) $(INSN_ATTR_H) toplev.h $(RECOG_H) $(EXCEPT_H) $(PARAMS_H) \
     $(TM_P_H) $(TARGET_H) $(CFGLAYOUT_H) $(TIMEVAR_H) $(TREE_PASS_H)  \
     $(SCHED_INT_H) $(GGC_H) $(TREE_H) $(LANGHOOKS_DEF_H) \
!    $(SEL_SCHED_IR_H) $(SEL_SCHED_DUMP_H) sel-sched.h alias-export.h
  sel-sched-dump.o : sel-sched-dump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
     $(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
     $(FUNCTION_H) $(INSN_ATTR_H) toplev.h $(RECOG_H) $(EXCEPT_H) $(PARAMS_H) \
*************** final.o : final.c $(CONFIG_H) $(SYSTEM_H
*** 3016,3022 ****
     $(EXCEPT_H) debug.h xcoffout.h $(TOPLEV_H) reload.h dwarf2out.h \
     $(TREE_PASS_H) $(BASIC_BLOCK_H) $(TM_P_H) $(TARGET_H) $(EXPR_H) \
     $(CFGLAYOUT_H) dbxout.h $(TIMEVAR_H) $(CGRAPH_H) $(COVERAGE_H) $(REAL_H) \
!    $(DF_H) vecprim.h $(GGC_H) $(CFGLOOP_H) $(PARAMS_H)
  recog.o : recog.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
     $(FUNCTION_H) $(BASIC_BLOCK_H) $(REGS_H) $(RECOG_H) $(EXPR_H) \
     $(FLAGS_H) insn-config.h $(INSN_ATTR_H) $(TOPLEV_H) output.h reload.h \
--- 3024,3030 ----
     $(EXCEPT_H) debug.h xcoffout.h $(TOPLEV_H) reload.h dwarf2out.h \
     $(TREE_PASS_H) $(BASIC_BLOCK_H) $(TM_P_H) $(TARGET_H) $(EXPR_H) \
     $(CFGLAYOUT_H) dbxout.h $(TIMEVAR_H) $(CGRAPH_H) $(COVERAGE_H) $(REAL_H) \
!    $(DF_H) vecprim.h $(GGC_H) $(CFGLOOP_H) $(PARAMS_H) alias-export.h
  recog.o : recog.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
     $(FUNCTION_H) $(BASIC_BLOCK_H) $(REGS_H) $(RECOG_H) $(EXPR_H) \
     $(FLAGS_H) insn-config.h $(INSN_ATTR_H) $(TOPLEV_H) output.h reload.h \
diff -cprdN -x .svn -x TAGS trunk/gcc/alias-export.c alias-export/gcc/alias-export.c
*** trunk/gcc/alias-export.c	Thu Jan  1 03:00:00 1970
--- alias-export/gcc/alias-export.c	Wed May 13 12:16:28 2009
***************
*** 0 ****
--- 1,779 ----
+ /* Export of alias/data dependency information to RTL.  
+    Copyright (C) 2009 Free Software Foundation, Inc.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, 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/>.  */
+ 
+ #include "config.h"
+ #include "system.h"
+ #include "coretypes.h"
+ #include "tm.h"
+ #include "tree.h"
+ #include "tm_p.h"
+ #include "basic-block.h"
+ #include "timevar.h"
+ #include "diagnostic.h"
+ #include "ggc.h"
+ #include "output.h"
+ #include "function.h"
+ #include "tree-dump.h"
+ #include "gimple.h"
+ #include "tree-flow.h"
+ #include "tree-pass.h"
+ #include "tree-ssa-alias.h"
+ #include "vec.h"
+ #include "bitmap.h"
+ #include "alias-export.h"
+ #include "emit-rtl.h"
+ #include "rtl.h"
+ #include "pointer-set.h"
+ #include "dbgcnt.h"
+ #include "cfgloop.h"
+ #include "tree-data-ref.h"
+ #include "tree-scalar-evolution.h"
+ #include "statistics.h"
+ 
+ /* The final orig_expr -> pt set map used in RTL.  */
+ static struct pointer_map_t *exprs_to_ptas = NULL;
+ 
+ /* The map of decls to stack partitions.  */
+ static struct pointer_map_t *decls_to_stack = NULL;
+ 
+ /* The map of partition representative decls to bitmaps that are
+    unified points-to sets for pointer decls.  */
+ static struct pointer_map_t *part_repr_to_pta = NULL;
+ 
+ /* The map of partition representative decls to bitmaps that have
+    set bits corresponding to decl uids of a partition.  */
+ static struct pointer_map_t *part_repr_to_part = NULL;
+ 
+ /* Saved escaped points-to solution.  */
+ static struct pt_solution gimple_df_escaped;
+ 
+ /* Alias export statistics counter.  */
+ static unsigned int alias_export_disambiguations = 0;
+ 
+ 
+ /* This structure holds exported data references and relations.  */
+ struct ddg_info_def
+ {
+   /* A hashtable for tree -> dataref mapping.  */
+   htab_t tree_to_dataref;
+ 
+   /* A hashtable for mapping dataref pairs to data dependence relation.  */
+   htab_t datarefs_pair_to_ddr;
+ 
+   /* TRUE for passes that perform code motion across loop branches, like SMS.
+      For other passes we assume it is safe to disambiguate references that are
+      dependent and distance vectors are known and non-zero.  */
+   bool pipelining_completed;
+ };
+ 
+ /* A struct holding dataref information for a given tree.  */
+ typedef struct {
+   const_tree ref;
+   data_reference_p drf;
+ } tree_dataref;
+ 
+ /* A struct for holding data dependence relations for datarefs pairs.  */
+ typedef struct {
+   data_reference_p a;
+   data_reference_p b;
+   ddr_p ddr;
+ } datarefs_pair_ddr;
+ 
+ /* Data references and data dependence relations exported from Tree-SSA
+    level for use on RTL level.  */
+ static struct ddg_info_def *ddg_info;
+ 
+ /* DDG export statistics counter.  */
+ static unsigned int ddg_export_disambiguations = 0;
+ 
+ 
+ /* Replace *PBASE with its stack representative in EXPR, if any.  
+    Return EXPR back.  */
+ static tree
+ maybe_replace_with_partition (tree expr, tree *pbase)
+ {
+   tree *pdecl;
+   
+   if (!decls_to_stack)
+     return expr;
+   pdecl = (tree *) pointer_map_contains (decls_to_stack, *pbase);
+   if (!pdecl
+       || *pdecl == *pbase)
+     return expr;
+   if (*pbase == expr)
+     return *pdecl;
+   *pbase = *pdecl;
+   return expr;
+ }
+ 
+ /* If some of PTVARS variables got partitioned, add all partition vars to 
+    PTVARS.  */
+ static void
+ add_partitioned_vars_to_ptset (bitmap ptvars)
+ {
+   bitmap_iterator bi;
+   unsigned i;
+   bitmap temp;
+   tree *pdecl;
+ 
+   temp = BITMAP_ALLOC (NULL);
+   EXECUTE_IF_SET_IN_BITMAP (ptvars, 0, i, bi)
+     if ((pdecl = (tree *) pointer_map_contains (decls_to_stack,
+                                                 referenced_var (i))))
+       bitmap_ior_into (temp, 
+                        *((bitmap *) pointer_map_contains (part_repr_to_part, 
+                                                           *pdecl)));
+   bitmap_ior_into (ptvars, temp);
+   BITMAP_FREE (temp);
+ }
+ 
+ /* Change points-to set for POINTER in PID so that it would
+    have all conflicting stack vars.  */
+ static void
+ mark_conflict_stack_vars (tree pointer, struct ptr_info_def *pid)
+ {
+   tree *pdecl;
+   bitmap temp;
+ 
+   if (!decls_to_stack)
+     return;
+ 
+   /* If pointer points to one of partition vars, make it point to all 
+      of them.  */
+   if (pid->pt.vars)
+     add_partitioned_vars_to_ptset (pid->pt.vars);
+ 
+   /* If pointer got paritioned itself, make its points-to set a union
+      of all the partition vars' points-to sets.  */
+   if ((pdecl = (tree *) pointer_map_contains (decls_to_stack, pointer)))
+     {
+       temp = *((bitmap *) pointer_map_contains (part_repr_to_pta, *pdecl));
+       bitmap_ior_into (pid->pt.vars, temp);
+     }
+ }
+ 
+ /* Record the final points-to set for EXPR and unshare it.  Returns 
+    the unshared expression or NULL_TREE, if EXPR cannot be used for 
+    alias/ddg export later.  */
+ tree
+ unshare_and_record_pta_info (tree expr)
+ {
+   tree base, old_expr;
+ 
+   /* No point saving anything for unhandled stuff.  */
+   if (! (SSA_VAR_P (expr)
+          || handled_component_p (expr)
+          || INDIRECT_REF_P (expr)))
+     return NULL_TREE;
+ 
+   /* Unshare the tree and do replacement in ddg info.  */
+   old_expr = expr;
+   expr = unshare_expr (expr);
+   if (flag_ddg_export)
+     replace_var_in_datarefs (old_expr, expr);
+ 
+   /* Record points-to set for expr.  */
+   base = expr;
+   while (handled_component_p (base))
+     base = TREE_OPERAND (base, 0);
+   if (INDIRECT_REF_P (base))
+     {
+       struct ptr_info_def **ppid, *pid;
+ 
+       base = TREE_OPERAND (base, 0);
+       if (TREE_CODE (base) == SSA_NAME
+           && (pid = SSA_NAME_PTR_INFO (base)) != NULL)
+         {
+           if (!exprs_to_ptas)
+             exprs_to_ptas = pointer_map_create ();
+           ppid = (struct ptr_info_def **) pointer_map_insert (exprs_to_ptas,
+                                                               expr);
+           *ppid = pid; 
+           
+           /* We can record stack conflicts in points-to sets here instead of
+              postponing this until end of expand, as incomplete stack sharing 
+              information might occur only for stack vars here, not for 
+              indirect-refs.  */
+           mark_conflict_stack_vars (base, pid);
+         }
+     }
+  
+   return expr;
+ }
+ 
+ /* Fixup stack-partitioned base var in EXPR and CONST_MEM.  */
+ static tree
+ rewrite_partitioned_mem_expr (const_rtx const_mem, tree expr)
+ {
+   tree base, *pbase;
+   rtx mem = CONST_CAST_RTX (const_mem);
+   
+   if (!decls_to_stack)
+     return expr;
+   
+   base = expr, pbase = &expr;
+   while (handled_component_p (base))
+     {
+       pbase = &TREE_OPERAND (base, 0);
+       base = TREE_OPERAND (base, 0);
+     }
+   if (DECL_P (base)
+       || TREE_CODE (base) == SSA_NAME)
+     {
+       expr = maybe_replace_with_partition (expr, pbase);
+       set_mem_orig_expr (mem, expr);
+     }
+ 
+   return expr;
+ }
+ 
+ /* Record the DECL mapping to its PART_DECL representative.  */
+ static void
+ map_decl_to_representative (tree decl, tree part_decl)
+ {
+   if (!decls_to_stack)
+     decls_to_stack = pointer_map_create ();
+   *((tree *) pointer_map_insert (decls_to_stack, decl)) = part_decl;
+ }
+ 
+ /* Create a bitmap in PMAP associated with DECL and return it.  */
+ static bitmap
+ map_decl_to_bitmap (struct pointer_map_t **pmap, tree decl)
+ {
+   bitmap temp = NULL, *ptemp;
+ 
+   if (!*pmap)
+     *pmap = pointer_map_create ();
+   ptemp = (bitmap *) pointer_map_contains (*pmap, decl);
+   if (ptemp)
+     {
+       temp = *ptemp;
+       gcc_assert (temp);
+     }
+   else
+     {
+       temp = BITMAP_ALLOC (NULL);
+       *((bitmap *) pointer_map_insert (*pmap, decl)) = temp;
+     }
+ 
+   return temp;
+ }
+ 
+ /* Save stack partitions.  DECL has PART_DECL as a representative.  
+    Also, create pta bitmaps so that alias analysis is not confused later.  */
+ void
+ record_stack_var_partition_for (tree decl, tree part_decl)
+ {
+   bitmap temp;
+   
+   /* First, record that decl has part_decl as a representative.  */
+   map_decl_to_representative (decl, part_decl);
+ 
+   /* Second, create a bitmap that represents all partition.  */
+   temp = map_decl_to_bitmap (&part_repr_to_part, part_decl);
+   if (DECL_P (part_decl))
+     bitmap_set_bit (temp, DECL_UID (part_decl));
+   if (DECL_P (decl))
+     bitmap_set_bit (temp, DECL_UID (decl));
+ 
+   /* Third, when decl is a pointer, we need to do the same 
+      for points-to sets.  */
+   if (TREE_CODE (decl) == SSA_NAME
+       && SSA_NAME_PTR_INFO (decl))
+     {
+       temp = map_decl_to_bitmap (&part_repr_to_pta, part_decl);
+       if (TREE_CODE (part_decl) == SSA_NAME
+           && SSA_NAME_PTR_INFO (part_decl))
+         bitmap_ior_into (temp, SSA_NAME_PTR_INFO (part_decl)->pt.vars);
+       bitmap_ior_into (temp, SSA_NAME_PTR_INFO (decl)->pt.vars);
+     }
+ }
+ 
+ /* Return the ptr-info-def structure for given expression.  */
+ static struct ptr_info_def *
+ get_exported_ptr_info (tree expr)
+ {
+   struct ptr_info_def **ppid;
+ 
+   if (! exprs_to_ptas)
+     return NULL;
+   ppid = (struct ptr_info_def **) pointer_map_contains (exprs_to_ptas, expr);
+   if (ppid)
+     return *ppid;
+   return NULL;
+ }
+ 
+ /* Save the above solution.  */
+ void
+ record_escaped_solution (struct pt_solution *escaped)
+ {
+   gimple_df_escaped = *escaped;
+   if (escaped->vars)
+     {
+       gimple_df_escaped.vars = BITMAP_ALLOC (NULL);
+       bitmap_copy (gimple_df_escaped.vars, escaped->vars);
+ 
+       /* We need to account for stack slot sharing also here.  */
+       if (decls_to_stack)
+         add_partitioned_vars_to_ptset (gimple_df_escaped.vars);
+     }
+ }
+ 
+ /* Functions to be called when needed to use exported information.  */
+ 
+ /* Main function to ask saved information about if REF1 and REF2 may
+    alias or not.  MEM1 and MEM2 are corresponding mems.  */
+ bool
+ alias_export_may_alias_p (const_rtx mem1, const_rtx mem2, tree ref1, tree ref2)
+ {
+   struct ptr_info_def *pid1, *pid2;
+   
+   if (! dbg_cnt (alias_export))
+     return true;
+   
+   ref1 = rewrite_partitioned_mem_expr (mem1, ref1);
+   ref2 = rewrite_partitioned_mem_expr (mem2, ref2);
+   pid1 = get_exported_ptr_info (ref1);
+   pid2 = get_exported_ptr_info (ref2);
+   if (! refs_may_alias_p_1 (ref1, ref2, pid1, pid2, &gimple_df_escaped))
+     {
+       alias_export_disambiguations++;
+       return false;
+     }
+ 
+   return true;
+ }
+ 
+ /* Free exported info.  */
+ void
+ free_alias_export_info (void)
+ {
+   statistics_counter_event (cfun, "Alias export disambiguations", 
+                             alias_export_disambiguations);
+   alias_export_disambiguations = 0;
+ 
+   if (exprs_to_ptas)
+     {
+       pointer_map_destroy (exprs_to_ptas);
+       exprs_to_ptas = NULL;
+     }
+   if (decls_to_stack)
+     {
+       pointer_map_destroy (decls_to_stack);
+       decls_to_stack = NULL;
+     }
+   if (part_repr_to_pta)
+     {
+       pointer_map_destroy (part_repr_to_pta);
+       part_repr_to_pta = NULL;
+     }
+   if (part_repr_to_part)
+     {
+       pointer_map_destroy (part_repr_to_part);
+       part_repr_to_part = NULL;
+     }
+   if (gimple_df_escaped.vars)
+     {
+       BITMAP_FREE (gimple_df_escaped.vars);
+       memset (&gimple_df_escaped, 0, sizeof gimple_df_escaped);
+     }
+ }
+ 
+ 
+ /* Data dependence export.  */
+ 
+ /* Hash a dataref T.  */
+ static hashval_t
+ htab_hash_tree (const tree_dataref *t)
+ {
+   return htab_hash_pointer (t->ref);
+ }
+ 
+ /* Equality function for struct tree_dataref.  */
+ static int
+ htab_eq_tree (const tree_dataref *t1, const tree_dataref *t2)
+ {
+   return t1->ref == t2->ref;
+ }
+ 
+ /* When freeing hashtable, free the dataref memory.  */
+ static void
+ htab_del_tree_dataref (tree_dataref *t)
+ {
+   if (t->drf)
+     free_data_ref (t->drf);
+ }
+ 
+ /* Hash function for the above.  */
+ static hashval_t
+ htab_hash_datarefs_pair (const datarefs_pair_ddr *dp)
+ {
+   return iterative_hash (&dp->a, sizeof (data_reference_p),
+ 			 htab_hash_pointer (dp->b));
+ }
+ 
+ /* Equality function for the above.  */
+ static int
+ htab_eq_datarefs_pair (const datarefs_pair_ddr *dp1,
+ 		       const datarefs_pair_ddr *dp2)
+ {
+   return dp1->a == dp2->a && dp1->b == dp2->b;
+ }
+ 
+ /* Free function for the above.  */
+ static void
+ htab_del_datarefs_pair (datarefs_pair_ddr *dp)
+ {
+   free_dependence_relation (dp->ddr);
+ }
+ 
+ /* Init the ddg_info structure holding the saved data.  */
+ static void
+ init_ddg_info (void)
+ {
+   gcc_assert (!ddg_info);
+ 
+   ddg_info = XCNEW (struct ddg_info_def);
+   ddg_info->tree_to_dataref
+    = htab_create (1, (htab_hash) htab_hash_tree, (htab_eq) htab_eq_tree,
+ 		  (htab_del) htab_del_tree_dataref);
+   ddg_info->datarefs_pair_to_ddr
+    = htab_create (1, (htab_hash) htab_hash_datarefs_pair,
+ 		  (htab_eq) htab_eq_datarefs_pair,
+ 		  (htab_del) htab_del_datarefs_pair);
+   ddg_info->pipelining_completed = false;
+ }
+ 
+ /* Save the data reference DRF in the ddg_info structure.  */
+ static void
+ record_data_reference (data_reference_p drf)
+ {
+   void **slot;
+   tree_dataref *td;
+ 
+   td = XNEW (tree_dataref);
+   td->ref = drf->ref;
+   td->drf = drf;
+ 
+   slot = htab_find_slot (ddg_info->tree_to_dataref, td, INSERT);
+   gcc_assert (!*slot);
+ 
+   *slot = td;
+ }
+ 
+ /* Save the data relation DDR in the ddg info structure.  */
+ static void
+ record_data_dependence_relation (ddr_p ddr)
+ {
+   void **slot;
+   datarefs_pair_ddr *dp;
+ 
+   dp = XNEW (datarefs_pair_ddr);
+   dp->a = ddr->a;
+   dp->b = ddr->b;
+   dp->ddr = ddr;
+ 
+   slot = htab_find_slot (ddg_info->datarefs_pair_to_ddr, dp, INSERT);
+   gcc_assert (!*slot);
+ 
+   *slot = dp;
+ }
+ 
+ /* Export ddg info for loop LOOP.  */
+ static void
+ record_ddg_info_for (struct loop *loop)
+ {
+   VEC (data_reference_p, heap) *datarefs = NULL;
+   VEC (ddr_p, heap) *ddrs = NULL;
+   unsigned int i;
+   data_reference_p drf;
+   ddr_p ddr;
+ 
+   compute_data_dependences_for_loop (loop, false, &datarefs, &ddrs);
+ 
+   if (dump_file && (dump_flags & TDF_DETAILS))
+     {
+       dump_data_references (dump_file, datarefs);
+       dump_ddrs (dump_file, ddrs);
+     }
+ 
+   for (i = 0; VEC_iterate (data_reference_p, datarefs, i, drf); i++)
+     {
+       /* We want to save only those data references that correspond to
+          iteration of innermost loop containing the reference.  */
+       if (!drf->ref || loop != loop_containing_stmt (drf->stmt))
+         continue;
+       record_data_reference (drf);
+     }
+ 
+   for (i = 0; VEC_iterate (ddr_p, ddrs, i, ddr); i++)
+     {
+       /* As above, we want to save only those DDRs that describe
+          relation of references for innermost loop containing them.  */
+       if (!(ddr->a && ddr->b)
+           || loop != loop_containing_stmt (ddr->a->stmt))
+         continue;
+       record_data_dependence_relation (ddr);
+     }
+ 
+   VEC_free (data_reference_p, heap, datarefs);
+   VEC_free (ddr_p, heap, ddrs);
+ }
+ 
+ /* For each loop in function, save datarefs and ddrs obtained via
+    compute_dependencies_for_loop into ddg_info.  */
+ static unsigned int
+ run_ddg_export (void)
+ {
+   bool inside_tree_loop_opt_p = !!current_loops;
+   bool dom_info_was_avail_p = dom_info_available_p (CDI_DOMINATORS);
+   struct loop *loop;
+   loop_iterator li;
+ 
+   if (!inside_tree_loop_opt_p)
+     loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
+ 
+   /* This can be more than actual number of loops, because number_of_loops ()
+      includes deleted loops.  */
+   if (number_of_loops () > 1)
+     {
+       if (!inside_tree_loop_opt_p)
+ 	scev_initialize ();
+       init_ddg_info ();
+ 
+       FOR_EACH_LOOP (li, loop, 0)
+         record_ddg_info_for (loop);
+ 
+       if (!inside_tree_loop_opt_p)
+ 	scev_finalize ();
+     }
+ 
+   if (!inside_tree_loop_opt_p)
+     loop_optimizer_finalize ();
+ 
+   if (!dom_info_was_avail_p)
+     free_dominance_info (CDI_DOMINATORS);
+ 
+   return 0;
+ }
+ 
+ /* Replace FROM tree to TO in ref fields of saved datarefs.  */
+ void
+ replace_var_in_datarefs (tree from, tree to)
+ {
+   void **slot;
+   tree_dataref td, *ptd;
+ 
+   if (!ddg_info)
+     return;
+ 
+   td.ref = from;
+   slot = htab_find_slot (ddg_info->tree_to_dataref, &td, NO_INSERT);
+ 
+   /* IVOPTS might want to change a memory reference for which no dataref was
+      produced.  However, it would be nice to enable this assert and see in
+      what cases it happens.  */
+   /* gcc_assert (slot); */
+   if (!slot)
+     return;
+ 
+   ptd = XNEW (tree_dataref);
+   ptd->ref = to;
+   ptd->drf = ((tree_dataref *) (*slot))->drf;
+   ((tree_dataref *) (*slot))->drf = NULL;
+   htab_clear_slot (ddg_info->tree_to_dataref, slot);
+   
+   slot = htab_find_slot (ddg_info->tree_to_dataref, ptd, INSERT);
+   gcc_assert (!*slot);
+   *slot = ptd;
+ }
+ 
+ /* Search for the dataref for T and return it if found, otherwise return
+    NULL.  */
+ 
+ static data_reference_p
+ find_dataref (const_tree t)
+ {
+   tree_dataref td, *ptd;
+ 
+   td.ref = t;
+   ptd = (tree_dataref *) htab_find (ddg_info->tree_to_dataref, &td);
+   return ptd ? ptd->drf : NULL;
+ }
+ 
+ /* Search for data dependence relation for DR1 and DR2, return it if found;
+    otherwise return NULL.  */
+ static ddr_p
+ find_ddr (data_reference_p dr1, data_reference_p dr2)
+ {
+   datarefs_pair_ddr dp, *pdp;
+ 
+   dp.a = dr1;
+   dp.b = dr2;
+   pdp = (datarefs_pair_ddr *) htab_find (ddg_info->datarefs_pair_to_ddr, &dp);
+   if (pdp)
+     return pdp->ddr;
+ 
+   dp.a = dr2;
+   dp.b = dr1;
+   pdp = (datarefs_pair_ddr *) htab_find (ddg_info->datarefs_pair_to_ddr, &dp);
+   return pdp ? pdp->ddr : NULL;
+ }
+ 
+ /* A callback for for_each_rtx to remove exported data for mems.  */
+ static int
+ walk_mems (rtx *x, void *data ATTRIBUTE_UNUSED)
+ {
+   if (MEM_P (*x) && MEM_ORIG_EXPR (*x) && find_dataref (MEM_ORIG_EXPR (*x)))
+     {
+       tree_dataref td;
+ 
+       td.ref = MEM_ORIG_EXPR (*x);
+       htab_remove_elt (ddg_info->tree_to_dataref, &td);
+ 
+       return -1;
+     }
+   
+   return 0;
+ }
+ 
+ /* Remove saved dependency data for INSN.  Used when INSN is in the loop that
+    was unrolled.  */
+ void
+ remove_exported_ddg_data (rtx insn)
+ {
+   if (!ddg_info)
+     return;
+ 
+   for_each_rtx (&PATTERN (insn), walk_mems, NULL);
+ }
+ 
+ /* Set pipelining-completed to B.  */
+ void
+ ddg_export_set_pipelining_completed (bool b)
+ {
+   if (ddg_info)
+     ddg_info->pipelining_completed = b;
+ }
+ 
+ /* Return TRUE if any of DIST_VECTS is non-zero.  */
+ static bool
+ nonzero_dist_vects (VEC (lambda_vector, heap) *dist_vects, int loops_count)
+ {
+   lambda_vector dist_v;
+   int i, j;
+ 
+   for (i = 0; VEC_iterate (lambda_vector, dist_vects, i, dist_v); i++)
+     for (j = 0; j < loops_count; j++)
+       if (dist_v[j])
+ 	return true;
+ 
+   return false;
+ }
+ 
+ /* Return TRUE if we cannot prove from exported DDG info that MEM1 and MEM2
+    are independent memory references.  When FOR_PIPELINING is true, do not
+    disambiguate references with non-zero distances.  */
+ bool
+ ddg_export_may_alias_p (tree t1, tree t2, bool for_pipelining)
+ {
+   data_reference_p drf1, drf2;
+   ddr_p ddr;
+ 
+   if (! dbg_cnt (ddg_export))
+     return true;
+ 
+   if (!ddg_info || !t1 || !t2)
+     return true;
+ 
+   drf1 = find_dataref (t1);
+   drf2 = find_dataref (t2);
+   if (!drf1 || !drf2)
+     return true;
+ 
+   ddr = find_ddr (drf1, drf2);
+   if (!ddr)
+     return true;
+ 
+   if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
+     {
+       ddg_export_disambiguations++;
+       return false;
+     }
+   
+   if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE 
+       && DDR_NUM_DIST_VECTS (ddr) > 0
+       && ! for_pipelining
+       && ! ddg_info->pipelining_completed
+       && nonzero_dist_vects (DDR_DIST_VECTS (ddr), DDR_NB_LOOPS (ddr)))
+     {
+       ddg_export_disambiguations++;
+       return false;
+     }
+   
+   return true;
+ }
+ 
+ /* Free ddg export info.  */
+ void
+ free_ddg_export_info (void)
+ {
+   if (!ddg_info)
+     return;
+ 
+   statistics_counter_event (cfun, "DDG export disambiguations", 
+                             ddg_export_disambiguations);
+   ddg_export_disambiguations = 0;
+ 
+   /* TODO: DDR_LOOP_NESTs are not free'd.  */
+   htab_delete (ddg_info->datarefs_pair_to_ddr);
+   htab_delete (ddg_info->tree_to_dataref);
+ 
+   free (ddg_info);
+   ddg_info = NULL;
+ }
+ 
+ /* Gate for ddg export pass.  */
+ static bool
+ gate_ddg_export (void)
+ {
+   return flag_ddg_export != 0;
+ }
+ 
+ struct gimple_opt_pass pass_gather_ddg_info =
+ {
+  {
+   GIMPLE_PASS,
+   "ddg-export",				/* name */
+   gate_ddg_export,	                /* gate */
+   run_ddg_export,			/* execute */
+   NULL,					/* sub */
+   NULL,					/* next */
+   0,					/* static_pass_number */
+   TV_NONE,				/* tv_id */
+   0,					/* properties_required */
+   0,					/* properties_provided */
+   0,					/* properties_destroyed */
+   0,					/* todo_flags_start */
+   TODO_dump_func                        /* todo_flags_finish */
+  }
+ };
+ 
+ 
+ 
diff -cprdN -x .svn -x TAGS trunk/gcc/alias-export.h alias-export/gcc/alias-export.h
*** trunk/gcc/alias-export.h	Thu Jan  1 03:00:00 1970
--- alias-export/gcc/alias-export.h	Tue May 12 16:50:57 2009
***************
*** 0 ****
--- 1,38 ----
+ /* Export of alias information to RTL.  
+    Copyright (C) 2009 Free Software Foundation, Inc.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, 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 GCC_ALIAS_EXPORT_H
+ #define GCC_ALIAS_EXPORT_H
+ 
+ #include "tree-ssa-alias.h"
+ 
+ extern tree unshare_and_record_pta_info (tree);
+ extern void record_escaped_solution (struct pt_solution *);
+ extern void record_stack_var_partition_for (tree, tree);
+ 
+ extern bool alias_export_may_alias_p (const_rtx, const_rtx, tree, tree);
+ extern bool ddg_export_may_alias_p (tree, tree, bool);
+ extern void replace_var_in_datarefs (tree, tree);
+ extern void remove_exported_ddg_data (rtx);
+ extern void ddg_export_set_pipelining_completed (bool);
+ 
+ extern void free_alias_export_info (void);
+ extern void free_ddg_export_info (void);
+ 
+ #endif /* GCC_ALIAS_EXPORT_H */
diff -cprdN -x .svn -x TAGS trunk/gcc/alias.c alias-export/gcc/alias.c
*** trunk/gcc/alias.c	Tue Apr 28 11:40:36 2009
--- alias-export/gcc/alias.c	Wed May 13 14:19:20 2009
*************** along with GCC; see the file COPYING3.  
*** 46,51 ****
--- 46,52 ----
  #include "tree-pass.h"
  #include "ipa-type-escape.h"
  #include "df.h"
+ #include "alias-export.h"
  
  /* The aliasing API provided here solves related but different problems:
  
*************** DEF_VEC_ALLOC_P(alias_set_entry,gc);
*** 250,255 ****
--- 251,280 ----
  /* The splay-tree used to store the various alias set entries.  */
  static GTY (()) VEC(alias_set_entry,gc) *alias_sets;
  
+ 
+ /* Check MEM_ORIG_EXPRs of two MEMs and if they are present query saved alias/ddg
+    information whether they may alias or not.  */
+ static bool
+ query_alias_export_info (const_rtx x, const_rtx mem)
+ {
+   tree x_orig_expr = MEM_ORIG_EXPR (x);
+   tree mem_orig_expr = MEM_ORIG_EXPR (mem);
+   bool ret = true;
+ 
+   if (x_orig_expr != NULL 
+       && mem_orig_expr != NULL
+       && x_orig_expr != mem_orig_expr)
+     {
+       if (flag_alias_export == 1)
+         ret = alias_export_may_alias_p (x, mem, x_orig_expr, mem_orig_expr);
+       if (flag_ddg_export == 1
+           && ret)
+         ret = ddg_export_may_alias_p (x_orig_expr, mem_orig_expr, false);
+     }
+ 
+   return ret;
+ }
+ 
  /* Returns a pointer to the alias set entry for ALIAS_SET, if there is
     such an entry, or NULL otherwise.  */
  
*************** walk_mems_2 (rtx *x, rtx mem)
*** 347,353 ****
  {
    if (MEM_P (*x))
      {
!       if (alias_sets_conflict_p (MEM_ALIAS_SET(*x), MEM_ALIAS_SET(mem)))
          return 1;
          
        return -1;  
--- 372,381 ----
  {
    if (MEM_P (*x))
      {
!       if (alias_sets_conflict_p (MEM_ALIAS_SET (*x), MEM_ALIAS_SET (mem))
!           && (! flag_ddg_export
!               || ddg_export_may_alias_p (MEM_ORIG_EXPR (*x),
!                                          MEM_ORIG_EXPR (mem), true)))
          return 1;
          
        return -1;  
*************** true_dependence (const_rtx mem, enum mac
*** 2266,2272 ****
    mem_addr = canon_rtx (mem_addr);
  
    if (! memrefs_conflict_p (GET_MODE_SIZE (mem_mode), mem_addr,
! 			    SIZE_FOR_MODE (x), x_addr, 0))
      return 0;
  
    if (aliases_everything_p (x))
--- 2294,2303 ----
    mem_addr = canon_rtx (mem_addr);
  
    if (! memrefs_conflict_p (GET_MODE_SIZE (mem_mode), mem_addr,
!                             SIZE_FOR_MODE (x), x_addr, 0))
!     return 0;
! 
!   if (! query_alias_export_info (x, mem))
      return 0;
  
    if (aliases_everything_p (x))
*************** canon_true_dependence (const_rtx mem, en
*** 2330,2336 ****
  
    x_addr = canon_rtx (x_addr);
    if (! memrefs_conflict_p (GET_MODE_SIZE (mem_mode), mem_addr,
! 			    SIZE_FOR_MODE (x), x_addr, 0))
      return 0;
  
    if (aliases_everything_p (x))
--- 2361,2370 ----
  
    x_addr = canon_rtx (x_addr);
    if (! memrefs_conflict_p (GET_MODE_SIZE (mem_mode), mem_addr,
!                             SIZE_FOR_MODE (x), x_addr, 0))
!     return 0;
! 
!   if (! query_alias_export_info (x, mem))
      return 0;
  
    if (aliases_everything_p (x))
*************** write_dependence_p (const_rtx mem, const
*** 2402,2409 ****
    x_addr = canon_rtx (x_addr);
    mem_addr = canon_rtx (mem_addr);
  
!   if (!memrefs_conflict_p (SIZE_FOR_MODE (mem), mem_addr,
! 			   SIZE_FOR_MODE (x), x_addr, 0))
      return 0;
  
    fixed_scalar
--- 2436,2446 ----
    x_addr = canon_rtx (x_addr);
    mem_addr = canon_rtx (mem_addr);
  
!   if (! memrefs_conflict_p (SIZE_FOR_MODE (mem), mem_addr,
!                             SIZE_FOR_MODE (x), x_addr, 0))
!     return 0;
! 
!   if (! query_alias_export_info (x, mem))
      return 0;
  
    fixed_scalar
diff -cprdN -x .svn -x TAGS trunk/gcc/builtins.c alias-export/gcc/builtins.c
*** trunk/gcc/builtins.c	Wed May  6 10:12:38 2009
--- alias-export/gcc/builtins.c	Wed May 13 13:50:21 2009
*************** get_memory_rtx (tree exp, tree len)
*** 1227,1232 ****
--- 1227,1233 ----
  	}
        set_mem_alias_set (mem, 0);
        set_mem_size (mem, NULL_RTX);
+       set_mem_orig_expr (mem, NULL_TREE);
      }
  
    return mem;
diff -cprdN -x .svn -x TAGS trunk/gcc/cfgexpand.c alias-export/gcc/cfgexpand.c
*** trunk/gcc/cfgexpand.c	Fri May  8 09:50:16 2009
--- alias-export/gcc/cfgexpand.c	Wed May 13 12:14:42 2009
*************** along with GCC; see the file COPYING3.  
*** 42,47 ****
--- 42,48 ----
  #include "tree-inline.h"
  #include "value-prof.h"
  #include "target.h"
+ #include "alias-export.h"
  #include "ssaexpand.h"
  
  
*************** static void
*** 774,789 ****
--- 775,794 ----
  union_stack_vars (size_t a, size_t b, HOST_WIDE_INT offset)
  {
    size_t i, last;
+   bool adressable;
  
    /* Update each element of partition B with the given offset,
       and merge them into partition A.  */
+   adressable = false;
    for (last = i = b; i != EOC; last = i, i = stack_vars[i].next)
      {
        stack_vars[i].offset += offset;
        stack_vars[i].representative = a;
+       adressable |= TREE_ADDRESSABLE (stack_vars[i].decl);
      }
    stack_vars[last].next = stack_vars[a].next;
    stack_vars[a].next = b;
+   TREE_ADDRESSABLE (stack_vars[a].decl) |= adressable;
  
    /* Update the required alignment of partition A to account for B.  */
    if (stack_vars[a].alignb < stack_vars[b].alignb)
*************** dump_stack_var_partition (void)
*** 912,917 ****
--- 917,937 ----
      }
  }
  
+ /* Save the generated partitions for alias.c, so we can say whether two 
+    vars actually occupy different stack locations.  */
+ 
+ static void
+ record_stack_var_partitions (void)
+ {
+   size_t i;
+   
+   /* Save all stack_vars partition info in the annotations.  */
+   for (i = 0; i < stack_vars_num; i++)
+     record_stack_var_partition_for (stack_vars[i].decl, 
+                                     stack_vars[stack_vars[i].representative].decl);
+ }
+ 
+ 
  /* Assign rtl to DECL at frame offset OFFSET.  */
  
  static void
*************** expand_used_vars (void)
*** 1651,1656 ****
--- 1671,1679 ----
  
        expand_stack_vars (NULL);
  
+       if (flag_alias_export)
+         record_stack_var_partitions ();
+ 
        fini_vars_expansion ();
      }
  
*************** discover_nonconstant_array_refs_r (tree 
*** 2321,2328 ****
        if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
  	{
  	  t = get_base_address (t);
! 	  if (t && DECL_P (t))
! 	    TREE_ADDRESSABLE (t) = 1;
  	}
  
        *walk_subtrees = 0;
--- 2344,2352 ----
        if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
  	{
  	  t = get_base_address (t);
! 	  if (t && DECL_P (t)
!               && DECL_MODE (t) != BLKmode)
!             TREE_ADDRESSABLE (t) = 1;
  	}
  
        *walk_subtrees = 0;
*************** gimple_expand_cfg (void)
*** 2465,2471 ****
    crtl->preferred_stack_boundary = STACK_BOUNDARY;
    cfun->cfg->max_jumptable_ents = 0;
  
- 
    /* Expand the variables recorded during gimple lowering.  */
    expand_used_vars ();
  
--- 2489,2494 ----
*************** gimple_expand_cfg (void)
*** 2500,2509 ****
  	 to select one of the potentially many RTLs for one DECL.  Instead
  	 of doing that we simply reset the MEM_EXPR of the RTL in question,
  	 then nobody can get at it and hence nobody can call DECL_RTL on it.  */
!       if (!DECL_RTL_SET_P (var))
! 	{
! 	  if (MEM_P (SA.partition_to_pseudo[i]))
! 	    set_mem_expr (SA.partition_to_pseudo[i], NULL);
  	}
      }
  
--- 2523,2533 ----
  	 to select one of the potentially many RTLs for one DECL.  Instead
  	 of doing that we simply reset the MEM_EXPR of the RTL in question,
  	 then nobody can get at it and hence nobody can call DECL_RTL on it.  */
!       if (!DECL_RTL_SET_P (var)
!           && MEM_P (SA.partition_to_pseudo[i]))
!         {
!           set_mem_expr (SA.partition_to_pseudo[i], NULL);
!           set_mem_orig_expr (SA.partition_to_pseudo[i], NULL);
  	}
      }
  
diff -cprdN -x .svn -x TAGS trunk/gcc/common.opt alias-export/gcc/common.opt
*** trunk/gcc/common.opt	Wed May  6 10:12:38 2009
--- alias-export/gcc/common.opt	Thu May  7 12:23:35 2009
*************** fexpensive-optimizations
*** 490,495 ****
--- 490,503 ----
  Common Report Var(flag_expensive_optimizations) Optimization
  Perform a number of minor, expensive optimizations
  
+ falias-export
+ Common Report Var(flag_alias_export) Optimization Init(1)
+ Save alias information on Tree-SSA to be used on RTL
+ 
+ fddg-export
+ Common Report Var(flag_ddg_export) Optimization Init(1)
+ Save alias information on Tree-SSA to be used on RTL
+ 
  fexcess-precision=
  Common Joined RejectNegative
  -fexcess-precision=[fast|standard]	Specify handling of excess floating-point precision
diff -cprdN -x .svn -x TAGS trunk/gcc/dbgcnt.def alias-export/gcc/dbgcnt.def
*** trunk/gcc/dbgcnt.def	Tue Apr 28 11:40:36 2009
--- alias-export/gcc/dbgcnt.def	Thu May  7 12:24:04 2009
*************** echo ubound: $ub
*** 141,146 ****
--- 141,147 ----
  */
  
  /* Debug counter definitions.  */
+ DEBUG_COUNTER (alias_export)
  DEBUG_COUNTER (auto_inc_dec)
  DEBUG_COUNTER (ccp)
  DEBUG_COUNTER (cfg_cleanup)
*************** DEBUG_COUNTER (cprop)
*** 149,154 ****
--- 150,156 ----
  DEBUG_COUNTER (dce)
  DEBUG_COUNTER (dce_fast)
  DEBUG_COUNTER (dce_ud)
+ DEBUG_COUNTER (ddg_export)
  DEBUG_COUNTER (delete_trivial_dead)
  DEBUG_COUNTER (df_byte_scan)
  DEBUG_COUNTER (dse)
diff -cprdN -x .svn -x TAGS trunk/gcc/emit-rtl.c alias-export/gcc/emit-rtl.c
*** trunk/gcc/emit-rtl.c	Tue Apr 28 11:40:36 2009
--- alias-export/gcc/emit-rtl.c	Wed May 13 14:19:40 2009
*************** along with GCC; see the file COPYING3.  
*** 58,63 ****
--- 58,64 ----
  #include "langhooks.h"
  #include "tree-pass.h"
  #include "df.h"
+ #include "alias-export.h"
  
  /* Commonly used modes.  */
  
*************** static int const_fixed_htab_eq (const vo
*** 192,199 ****
  static rtx lookup_const_fixed (rtx);
  static hashval_t mem_attrs_htab_hash (const void *);
  static int mem_attrs_htab_eq (const void *, const void *);
! static mem_attrs *get_mem_attrs (alias_set_type, tree, rtx, rtx, unsigned int,
! 				 enum machine_mode);
  static hashval_t reg_attrs_htab_hash (const void *);
  static int reg_attrs_htab_eq (const void *, const void *);
  static reg_attrs *get_reg_attrs (tree, int);
--- 193,200 ----
  static rtx lookup_const_fixed (rtx);
  static hashval_t mem_attrs_htab_hash (const void *);
  static int mem_attrs_htab_eq (const void *, const void *);
! static mem_attrs *get_mem_attrs (alias_set_type, tree, tree, rtx, rtx, 
! 				 unsigned int, enum machine_mode);
  static hashval_t reg_attrs_htab_hash (const void *);
  static int reg_attrs_htab_eq (const void *, const void *);
  static reg_attrs *get_reg_attrs (tree, int);
*************** mem_attrs_htab_hash (const void *x)
*** 295,301 ****
    return (p->alias ^ (p->align * 1000)
  	  ^ ((p->offset ? INTVAL (p->offset) : 0) * 50000)
  	  ^ ((p->size ? INTVAL (p->size) : 0) * 2500000)
! 	  ^ (size_t) iterative_hash_expr (p->expr, 0));
  }
  
  /* Returns nonzero if the value represented by X (which is really a
--- 296,304 ----
    return (p->alias ^ (p->align * 1000)
  	  ^ ((p->offset ? INTVAL (p->offset) : 0) * 50000)
  	  ^ ((p->size ? INTVAL (p->size) : 0) * 2500000)
! 	  ^ (size_t) iterative_hash_expr (p->expr, 
!                                           iterative_hash_expr (p->orig_expr, 
!                                                                0)));
  }
  
  /* Returns nonzero if the value represented by X (which is really a
*************** mem_attrs_htab_eq (const void *x, const 
*** 312,318 ****
  	  && p->size == q->size && p->align == q->align
  	  && (p->expr == q->expr
  	      || (p->expr != NULL_TREE && q->expr != NULL_TREE
! 		  && operand_equal_p (p->expr, q->expr, 0))));
  }
  
  /* Allocate a new mem_attrs structure and insert it into the hash table if
--- 315,324 ----
  	  && p->size == q->size && p->align == q->align
  	  && (p->expr == q->expr
  	      || (p->expr != NULL_TREE && q->expr != NULL_TREE
! 		  && operand_equal_p (p->expr, q->expr, 0)))
!           && (p->orig_expr == q->orig_expr
!               || (p->orig_expr != NULL_TREE && q->orig_expr != NULL_TREE
!                   && operand_equal_p (p->orig_expr, q->orig_expr, 0))));
  }
  
  /* Allocate a new mem_attrs structure and insert it into the hash table if
*************** mem_attrs_htab_eq (const void *x, const 
*** 320,327 ****
     MEM of mode MODE.  */
  
  static mem_attrs *
! get_mem_attrs (alias_set_type alias, tree expr, rtx offset, rtx size,
! 	       unsigned int align, enum machine_mode mode)
  {
    mem_attrs attrs;
    void **slot;
--- 326,333 ----
     MEM of mode MODE.  */
  
  static mem_attrs *
! get_mem_attrs (alias_set_type alias, tree expr, tree orig_expr, rtx offset, 
! 	       rtx size, unsigned int align, enum machine_mode mode)
  {
    mem_attrs attrs;
    void **slot;
*************** get_mem_attrs (alias_set_type alias, tre
*** 329,335 ****
    /* If everything is the default, we can just return zero.
       This must match what the corresponding MEM_* macros return when the
       field is not present.  */
!   if (alias == 0 && expr == 0 && offset == 0
        && (size == 0
  	  || (mode != BLKmode && GET_MODE_SIZE (mode) == INTVAL (size)))
        && (STRICT_ALIGNMENT && mode != BLKmode
--- 335,341 ----
    /* If everything is the default, we can just return zero.
       This must match what the corresponding MEM_* macros return when the
       field is not present.  */
!   if (alias == 0 && expr == 0 && orig_expr == 0 && offset == 0
        && (size == 0
  	  || (mode != BLKmode && GET_MODE_SIZE (mode) == INTVAL (size)))
        && (STRICT_ALIGNMENT && mode != BLKmode
*************** get_mem_attrs (alias_set_type alias, tre
*** 338,343 ****
--- 344,350 ----
  
    attrs.alias = alias;
    attrs.expr = expr;
+   attrs.orig_expr = orig_expr;
    attrs.offset = offset;
    attrs.size = size;
    attrs.align = align;
*************** set_mem_attributes_minus_bitpos (rtx ref
*** 1588,1593 ****
--- 1595,1601 ----
  {
    alias_set_type alias = MEM_ALIAS_SET (ref);
    tree expr = MEM_EXPR (ref);
+   tree orig_expr = NULL_TREE;
    rtx offset = MEM_OFFSET (ref);
    rtx size = MEM_SIZE (ref);
    unsigned int align = MEM_ALIGN (ref);
*************** set_mem_attributes_minus_bitpos (rtx ref
*** 1653,1658 ****
--- 1661,1668 ----
        tree base;
        bool align_computed = false;
  
+       orig_expr = t;
+ 
        if (TREE_THIS_VOLATILE (t))
  	MEM_VOLATILE_P (ref) = 1;
  
*************** set_mem_attributes_minus_bitpos (rtx ref
*** 1837,1847 ****
  	 we're overlapping.  */
        offset = NULL;
        expr = NULL;
      }
- 
-   /* Now set the attributes we computed above.  */
    MEM_ATTRS (ref)
!     = get_mem_attrs (alias, expr, offset, size, align, GET_MODE (ref));
  
    /* If this is already known to be a scalar or aggregate, we are done.  */
    if (MEM_IN_STRUCT_P (ref) || MEM_SCALAR_P (ref))
--- 1847,1865 ----
  	 we're overlapping.  */
        offset = NULL;
        expr = NULL;
+       orig_expr = NULL;
+     }
+   
+   /* Now set the attributes we computed above, but unshare orig_expr first.  */
+   if (orig_expr)
+     {
+       if (flag_alias_export || flag_ddg_export)
+         orig_expr = unshare_and_record_pta_info (orig_expr);
+       else
+         orig_expr = NULL_TREE;
      }
    MEM_ATTRS (ref)
!     = get_mem_attrs (alias, expr, orig_expr, offset, size, align, GET_MODE (ref));
  
    /* If this is already known to be a scalar or aggregate, we are done.  */
    if (MEM_IN_STRUCT_P (ref) || MEM_SCALAR_P (ref))
*************** set_mem_alias_set (rtx mem, alias_set_ty
*** 1871,1879 ****
    gcc_assert (alias_sets_conflict_p (set, MEM_ALIAS_SET (mem)));
  #endif
  
!   MEM_ATTRS (mem) = get_mem_attrs (set, MEM_EXPR (mem), MEM_OFFSET (mem),
! 				   MEM_SIZE (mem), MEM_ALIGN (mem),
! 				   GET_MODE (mem));
  }
  
  /* Set the alignment of MEM to ALIGN bits.  */
--- 1889,1897 ----
    gcc_assert (alias_sets_conflict_p (set, MEM_ALIAS_SET (mem)));
  #endif
  
!   MEM_ATTRS (mem) = get_mem_attrs (set, MEM_EXPR (mem), MEM_ORIG_EXPR (mem),
! 				   MEM_OFFSET (mem), MEM_SIZE (mem), 
! 				   MEM_ALIGN (mem), GET_MODE (mem));
  }
  
  /* Set the alignment of MEM to ALIGN bits.  */
*************** void
*** 1882,1889 ****
  set_mem_align (rtx mem, unsigned int align)
  {
    MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem),
! 				   MEM_OFFSET (mem), MEM_SIZE (mem), align,
! 				   GET_MODE (mem));
  }
  
  /* Set the expr for MEM to EXPR.  */
--- 1900,1907 ----
  set_mem_align (rtx mem, unsigned int align)
  {
    MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem),
! 				   MEM_ORIG_EXPR (mem), MEM_OFFSET (mem), 
! 				   MEM_SIZE (mem), align, GET_MODE (mem));
  }
  
  /* Set the expr for MEM to EXPR.  */
*************** set_mem_align (rtx mem, unsigned int ali
*** 1891,1899 ****
  void
  set_mem_expr (rtx mem, tree expr)
  {
    MEM_ATTRS (mem)
!     = get_mem_attrs (MEM_ALIAS_SET (mem), expr, MEM_OFFSET (mem),
! 		     MEM_SIZE (mem), MEM_ALIGN (mem), GET_MODE (mem));
  }
  
  /* Set the offset of MEM to OFFSET.  */
--- 1909,1941 ----
  void
  set_mem_expr (rtx mem, tree expr)
  {
+   tree orig_expr = MEM_ORIG_EXPR (mem);
+ 
+   /* If MEM_EXPR changes, clear MEM_ORIG_EXPR.  If we still can preserve it,
+      we insert set_mem_orig_expr call right after this function call.  */
+   if (!expr || !mem_expr_equal_p (MEM_EXPR (mem), expr))
+     orig_expr = NULL_TREE;
+   
    MEM_ATTRS (mem)
!     = get_mem_attrs (MEM_ALIAS_SET (mem), expr, orig_expr,
! 		     MEM_OFFSET (mem), MEM_SIZE (mem), MEM_ALIGN (mem), 
! 		     GET_MODE (mem));
! }
! 
! 
! /* Set the original expr for MEM to ORIG_EXPR.  */
! 
! void
! set_mem_orig_expr (rtx mem, tree orig_expr)
! {
!   if (orig_expr 
!       && currently_expanding_to_rtl
!       && (flag_alias_export || flag_ddg_export))
!     orig_expr = unshare_and_record_pta_info (orig_expr);
!   MEM_ATTRS (mem)
!     = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem), orig_expr,
! 		     MEM_OFFSET (mem), MEM_SIZE (mem), MEM_ALIGN (mem), 
! 		     GET_MODE (mem));
  }
  
  /* Set the offset of MEM to OFFSET.  */
*************** set_mem_expr (rtx mem, tree expr)
*** 1901,1909 ****
  void
  set_mem_offset (rtx mem, rtx offset)
  {
    MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem),
! 				   offset, MEM_SIZE (mem), MEM_ALIGN (mem),
! 				   GET_MODE (mem));
  }
  
  /* Set the size of MEM to SIZE.  */
--- 1943,1958 ----
  void
  set_mem_offset (rtx mem, rtx offset)
  {
+   tree orig_expr = MEM_ORIG_EXPR (mem);
+ 
+   /* If MEM_EXPR changes, clear MEM_ORIG_EXPR.  If we still can preserve it,
+      we insert set_mem_orig_expr call right after this function call.  */
+   if (offset != MEM_OFFSET (mem))
+     orig_expr = NULL_TREE;
+ 
    MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem),
! 				   orig_expr, offset, MEM_SIZE (mem),
! 				   MEM_ALIGN (mem), GET_MODE (mem));
  }
  
  /* Set the size of MEM to SIZE.  */
*************** void
*** 1912,1919 ****
  set_mem_size (rtx mem, rtx size)
  {
    MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem),
! 				   MEM_OFFSET (mem), size, MEM_ALIGN (mem),
! 				   GET_MODE (mem));
  }
  
  /* Return a memory reference like MEMREF, but with its mode changed to MODE
--- 1961,1968 ----
  set_mem_size (rtx mem, rtx size)
  {
    MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem),
! 				   MEM_ORIG_EXPR (mem), MEM_OFFSET (mem), 
! 				   size, MEM_ALIGN (mem), GET_MODE (mem));
  }
  
  /* Return a memory reference like MEMREF, but with its mode changed to MODE
*************** change_address (rtx memref, enum machine
*** 1980,1986 ****
      }
  
    MEM_ATTRS (new_rtx)
!     = get_mem_attrs (MEM_ALIAS_SET (memref), 0, 0, size, align, mmode);
  
    return new_rtx;
  }
--- 2029,2035 ----
      }
  
    MEM_ATTRS (new_rtx)
!     = get_mem_attrs (MEM_ALIAS_SET (memref), 0, 0, 0, size, align, mmode);
  
    return new_rtx;
  }
*************** adjust_address_1 (rtx memref, enum machi
*** 2063,2069 ****
      size = plus_constant (MEM_SIZE (memref), -offset);
  
    MEM_ATTRS (new_rtx) = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_EXPR (memref),
! 				   memoffset, size, memalign, GET_MODE (new_rtx));
  
    /* At some point, we should validate that this offset is within the object,
       if all the appropriate values are known.  */
--- 2112,2122 ----
      size = plus_constant (MEM_SIZE (memref), -offset);
  
    MEM_ATTRS (new_rtx) = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_EXPR (memref),
!                                        (offset != 0 || size == NULL
!                                         || GET_MODE_SIZE (mode) > INTVAL (size))
!                                        ? NULL_TREE
!                                        : MEM_ORIG_EXPR (memref), 
!                                        memoffset, size, memalign, GET_MODE (new_rtx));
  
    /* At some point, we should validate that this offset is within the object,
       if all the appropriate values are known.  */
*************** offset_address (rtx memref, rtx offset, 
*** 2119,2126 ****
    /* Update the alignment to reflect the offset.  Reset the offset, which
       we don't know.  */
    MEM_ATTRS (new_rtx)
!     = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_EXPR (memref), 0, 0,
! 		     MIN (MEM_ALIGN (memref), pow2 * BITS_PER_UNIT),
  		     GET_MODE (new_rtx));
    return new_rtx;
  }
--- 2172,2180 ----
    /* Update the alignment to reflect the offset.  Reset the offset, which
       we don't know.  */
    MEM_ATTRS (new_rtx)
!     = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_EXPR (memref), 
! 		     MEM_ORIG_EXPR (memref), 0, 0, 
!                      MIN (MEM_ALIGN (memref), pow2 * BITS_PER_UNIT),
  		     GET_MODE (new_rtx));
    return new_rtx;
  }
*************** widen_memory_access (rtx memref, enum ma
*** 2223,2231 ****
  
    /* The widened memory may alias other stuff, so zap the alias set.  */
    /* ??? Maybe use get_alias_set on any remaining expression.  */
! 
!   MEM_ATTRS (new_rtx) = get_mem_attrs (0, expr, memoffset, GEN_INT (size),
! 				   MEM_ALIGN (new_rtx), mode);
  
    return new_rtx;
  }
--- 2277,2285 ----
  
    /* The widened memory may alias other stuff, so zap the alias set.  */
    /* ??? Maybe use get_alias_set on any remaining expression.  */
!   MEM_ATTRS (new_rtx) = get_mem_attrs (0, expr, NULL_TREE, memoffset, 
!                                        GEN_INT (size), MEM_ALIGN (new_rtx), 
!                                        mode);
  
    return new_rtx;
  }
*************** get_spill_slot_decl (bool force_build_p)
*** 2251,2257 ****
  
    rd = gen_rtx_MEM (BLKmode, frame_pointer_rtx);
    MEM_NOTRAP_P (rd) = 1;
!   MEM_ATTRS (rd) = get_mem_attrs (new_alias_set (), d, const0_rtx,
  				  NULL_RTX, 0, BLKmode);
    SET_DECL_RTL (d, rd);
  
--- 2305,2311 ----
  
    rd = gen_rtx_MEM (BLKmode, frame_pointer_rtx);
    MEM_NOTRAP_P (rd) = 1;
!   MEM_ATTRS (rd) = get_mem_attrs (new_alias_set (), d, NULL_TREE, const0_rtx,
  				  NULL_RTX, 0, BLKmode);
    SET_DECL_RTL (d, rd);
  
*************** set_mem_attrs_for_spill (rtx mem)
*** 2283,2289 ****
        && GET_CODE (XEXP (addr, 1)) == CONST_INT)
      offset = XEXP (addr, 1);
  
!   MEM_ATTRS (mem) = get_mem_attrs (alias, expr, offset,
  				   MEM_SIZE (mem), MEM_ALIGN (mem),
  				   GET_MODE (mem));
    MEM_NOTRAP_P (mem) = 1;
--- 2337,2343 ----
        && GET_CODE (XEXP (addr, 1)) == CONST_INT)
      offset = XEXP (addr, 1);
  
!   MEM_ATTRS (mem) = get_mem_attrs (alias, expr, NULL_TREE, offset,
  				   MEM_SIZE (mem), MEM_ALIGN (mem),
  				   GET_MODE (mem));
    MEM_NOTRAP_P (mem) = 1;
diff -cprdN -x .svn -x TAGS trunk/gcc/emit-rtl.h alias-export/gcc/emit-rtl.h
*** trunk/gcc/emit-rtl.h	Wed Apr  8 13:59:49 2009
--- alias-export/gcc/emit-rtl.h	Tue Apr 14 15:40:33 2009
*************** extern void set_mem_align (rtx, unsigned
*** 29,34 ****
--- 29,37 ----
  /* Set the expr for MEM to EXPR.  */
  extern void set_mem_expr (rtx, tree);
  
+ /* Set the original expr for MEM to ORIG_EXPR.  */
+ extern void set_mem_orig_expr (rtx, tree);
+ 
  /* Set the offset for MEM to OFFSET.  */
  extern void set_mem_offset (rtx, rtx);
  
diff -cprdN -x .svn -x TAGS trunk/gcc/expr.c alias-export/gcc/expr.c
*** trunk/gcc/expr.c	Fri May  8 09:50:16 2009
--- alias-export/gcc/expr.c	Fri May  8 10:22:41 2009
*************** expand_expr_real_1 (tree exp, rtx target
*** 7578,7583 ****
--- 7578,7585 ----
  	op0 = memory_address (mode, op0);
  	temp = gen_rtx_MEM (mode, op0);
  	set_mem_attributes (temp, TMR_ORIGINAL (exp), 0);
+         if (! MEM_ORIG_EXPR (temp))
+           set_mem_orig_expr (temp, TMR_ORIGINAL (exp));
        }
        return temp;
  
diff -cprdN -x .svn -x TAGS trunk/gcc/final.c alias-export/gcc/final.c
*** trunk/gcc/final.c	Wed May 13 10:45:32 2009
--- alias-export/gcc/final.c	Wed May 13 10:56:01 2009
*************** along with GCC; see the file COPYING3.  
*** 79,84 ****
--- 79,85 ----
  #include "vecprim.h"
  #include "ggc.h"
  #include "cfgloop.h"
+ #include "alias-export.h"
  #include "params.h"
  
  #ifdef XCOFF_DEBUGGING_INFO
*************** rest_of_clean_state (void)
*** 4323,4328 ****
--- 4324,4334 ----
  
    free_bb_for_insn ();
  
+   if (flag_alias_export)
+     free_alias_export_info ();
+   if (flag_ddg_export)
+     free_ddg_export_info ();
+ 
    if (targetm.binds_local_p (current_function_decl))
      {
        unsigned int pref = crtl->preferred_stack_boundary;
diff -cprdN -x .svn -x TAGS trunk/gcc/function.c alias-export/gcc/function.c
*** trunk/gcc/function.c	Tue Apr 28 11:40:36 2009
--- alias-export/gcc/function.c	Tue Apr 28 12:32:15 2009
*************** assign_parms_unsplit_complex (struct ass
*** 3095,3101 ****
  	  /* Set MEM_EXPR to the original decl, i.e. to PARM,
  	     instead of the copy of decl, i.e. FNARGS.  */
  	  if (DECL_INCOMING_RTL (parm) && MEM_P (DECL_INCOMING_RTL (parm)))
! 	    set_mem_expr (DECL_INCOMING_RTL (parm), parm);
  	}
  
        fnargs = TREE_CHAIN (fnargs);
--- 3095,3104 ----
  	  /* Set MEM_EXPR to the original decl, i.e. to PARM,
  	     instead of the copy of decl, i.e. FNARGS.  */
  	  if (DECL_INCOMING_RTL (parm) && MEM_P (DECL_INCOMING_RTL (parm)))
! 	    {
! 	      set_mem_expr (DECL_INCOMING_RTL (parm), parm);
! 	      set_mem_orig_expr (DECL_INCOMING_RTL (parm), parm);
! 	    }
  	}
  
        fnargs = TREE_CHAIN (fnargs);
diff -cprdN -x .svn -x TAGS trunk/gcc/loop-unroll.c alias-export/gcc/loop-unroll.c
*** trunk/gcc/loop-unroll.c	Mon Apr  6 13:32:45 2009
--- alias-export/gcc/loop-unroll.c	Tue Apr 21 19:56:46 2009
*************** along with GCC; see the file COPYING3.  
*** 33,38 ****
--- 33,39 ----
  #include "expr.h"
  #include "hashtab.h"
  #include "recog.h"    
+ #include "alias-export.h"
  
  /* This pass performs loop unrolling and peeling.  We only perform these
     optimizations on innermost loops (with single exception) because
*************** apply_opt_in_copies (struct opt_info *op
*** 2207,2212 ****
--- 2208,2216 ----
                    expand_var_during_unrolling (ves, insn);
                  }
              }
+ 
+           if (flag_ddg_export)
+             remove_exported_ddg_data (insn);
            orig_insn = NEXT_INSN (orig_insn);
          }
      }
*************** apply_opt_in_copies (struct opt_info *op
*** 2245,2250 ****
--- 2249,2257 ----
            
            if (!INSN_P (orig_insn))
   	    continue;
+ 
+           if (flag_ddg_export)
+             remove_exported_ddg_data (orig_insn);
            
            ivts_templ.insn = orig_insn;
            if (opt_info->insns_to_split)
diff -cprdN -x .svn -x TAGS trunk/gcc/modulo-sched.c alias-export/gcc/modulo-sched.c
*** trunk/gcc/modulo-sched.c	Mon Apr  6 13:32:45 2009
--- alias-export/gcc/modulo-sched.c	Thu May  7 15:30:45 2009
*************** along with GCC; see the file COPYING3.  
*** 48,53 ****
--- 48,54 ----
  #include "timevar.h"
  #include "tree-pass.h"
  #include "dbgcnt.h"
+ #include "alias-export.h"
  
  #ifdef INSN_SCHEDULING
  
*************** rest_of_handle_sms (void)
*** 2875,2880 ****
--- 2876,2884 ----
        bb->aux = bb->next_bb;
    free_dominance_info (CDI_DOMINATORS);
    cfg_layout_finalize ();
+ 
+   if (flag_ddg_export)
+     ddg_export_set_pipelining_completed (true);
  #endif /* INSN_SCHEDULING */
    return 0;
  }
diff -cprdN -x .svn -x TAGS trunk/gcc/passes.c alias-export/gcc/passes.c
*** trunk/gcc/passes.c	Wed May 13 10:45:32 2009
--- alias-export/gcc/passes.c	Wed May 13 14:20:29 2009
*************** init_optimization_passes (void)
*** 664,669 ****
--- 664,670 ----
  	  NEXT_PASS (pass_complete_unroll);
  	  NEXT_PASS (pass_parallelize_loops);
  	  NEXT_PASS (pass_loop_prefetch);
+ 	  NEXT_PASS (pass_gather_ddg_info);
  	  NEXT_PASS (pass_iv_optimize);
  	  NEXT_PASS (pass_tree_loop_done);
  	}
*************** init_optimization_passes (void)
*** 699,704 ****
--- 700,706 ----
        NEXT_PASS (pass_uncprop);
        NEXT_PASS (pass_local_pure_const);
      }
+ 
    NEXT_PASS (pass_cleanup_eh);
    NEXT_PASS (pass_nrv);
    NEXT_PASS (pass_mudflap_2);
diff -cprdN -x .svn -x TAGS trunk/gcc/rtl.h alias-export/gcc/rtl.h
*** trunk/gcc/rtl.h	Wed May  6 10:12:38 2009
--- alias-export/gcc/rtl.h	Thu May  7 18:21:33 2009
*************** typedef struct GTY(()) mem_attrs
*** 146,151 ****
--- 146,152 ----
    rtx size;			/* Size in bytes, as a CONST_INT.  */
    alias_set_type alias;		/* Memory alias set.  */
    unsigned int align;		/* Alignment of MEM in bits.  */
+   tree orig_expr;		/* Explicit original tree expression.  */
  } mem_attrs;
  
  /* Structure used to describe the attributes of a REG in similar way as
*************** do {						\
*** 1220,1225 ****
--- 1221,1231 ----
   : (STRICT_ALIGNMENT && GET_MODE (RTX) != BLKmode			\
      ? GET_MODE_ALIGNMENT (GET_MODE (RTX)) : BITS_PER_UNIT))
  
+ /* For a MEM rtx, the decl it is known to refer to, if it is known to
+    refer to part of a DECL.  It may also be a COMPONENT_REF.  */
+ #define MEM_ORIG_EXPR(RTX)						\
+ (MEM_ATTRS (RTX) == 0 ? 0 : MEM_ATTRS (RTX)->orig_expr)
+ 
  /* For a REG rtx, the decl it is known to refer to, if it is known to
     refer to part of a DECL.  */
  #define REG_EXPR(RTX) (REG_ATTRS (RTX) == 0 ? 0 : REG_ATTRS (RTX)->decl)
*************** extern void simplify_using_condition (rt
*** 2335,2340 ****
--- 2341,2347 ----
  
  /* In final.c  */
  extern unsigned int compute_alignments (void);
+ 
  
  struct rtl_hooks
  {
diff -cprdN -x .svn -x TAGS trunk/gcc/sel-sched.c alias-export/gcc/sel-sched.c
*** trunk/gcc/sel-sched.c	Tue Apr 28 19:54:51 2009
--- alias-export/gcc/sel-sched.c	Thu May  7 15:25:02 2009
*************** along with GCC; see the file COPYING3.  
*** 51,56 ****
--- 51,57 ----
  #include "sel-sched-dump.h"
  #include "sel-sched.h"
  #include "dbgcnt.h"
+ #include "alias-export.h"
  
  /* Implementation of selective scheduling approach.
     The below implementation follows the original approach with the following
*************** sel_global_finish (void)
*** 7306,7311 ****
--- 7307,7316 ----
  
    free_sched_pools ();
    free_dominance_info (CDI_DOMINATORS);
+ 
+   if (flag_ddg_export
+       && flag_sel_sched_pipelining)
+     ddg_export_set_pipelining_completed (true);
  }
  
  /* Return true when we need to skip selective scheduling.  Used for debugging.  */
diff -cprdN -x .svn -x TAGS trunk/gcc/statistics.c alias-export/gcc/statistics.c
*** trunk/gcc/statistics.c	Mon Apr  6 13:32:45 2009
--- alias-export/gcc/statistics.c	Thu May  7 18:26:02 2009
*************** hash_statistics_free (void *p)
*** 82,88 ****
  static htab_t
  curr_statistics_hash (void)
  {
!   unsigned idx = current_pass->static_pass_number;
  
    if (idx < nr_statistics_hashes
        && statistics_hashes[idx] != NULL)
--- 82,91 ----
  static htab_t
  curr_statistics_hash (void)
  {
!   unsigned idx;
! 
!   gcc_assert (current_pass->static_pass_number >= 0);
!   idx = current_pass->static_pass_number;
  
    if (idx < nr_statistics_hashes
        && statistics_hashes[idx] != NULL)
*************** statistics_counter_event (struct functio
*** 294,302 ****
        || incr == 0)
      return;
  
!   counter = lookup_or_add_counter (curr_statistics_hash (), id, 0, false);
!   gcc_assert (!counter->histogram_p);
!   counter->count += incr;
  
    if (!statistics_dump_file
        || !(statistics_dump_flags & TDF_DETAILS))
--- 297,308 ----
        || incr == 0)
      return;
  
!   if (current_pass->static_pass_number != -1)
!     {
!       counter = lookup_or_add_counter (curr_statistics_hash (), id, 0, false);
!       gcc_assert (!counter->histogram_p);
!       counter->count += incr;
!     }
  
    if (!statistics_dump_file
        || !(statistics_dump_flags & TDF_DETAILS))
diff -cprdN -x .svn -x TAGS trunk/gcc/tree-pass.h alias-export/gcc/tree-pass.h
*** trunk/gcc/tree-pass.h	Wed May 13 10:45:32 2009
--- alias-export/gcc/tree-pass.h	Wed May 13 10:55:58 2009
*************** extern struct rtl_opt_pass pass_branch_t
*** 498,503 ****
--- 498,504 ----
  extern struct rtl_opt_pass pass_leaf_regs;
  extern struct rtl_opt_pass pass_split_before_sched2;
  extern struct rtl_opt_pass pass_sched2;
+ extern struct gimple_opt_pass pass_gather_ddg_info;
  extern struct rtl_opt_pass pass_stack_regs;
  extern struct rtl_opt_pass pass_stack_regs_run;
  extern struct rtl_opt_pass pass_df_finish;
diff -cprdN -x .svn -x TAGS trunk/gcc/tree-ssa-alias.c alias-export/gcc/tree-ssa-alias.c
*** trunk/gcc/tree-ssa-alias.c	Tue Apr 21 11:12:58 2009
--- alias-export/gcc/tree-ssa-alias.c	Tue Apr 28 12:26:19 2009
*************** along with GCC; see the file COPYING3.  
*** 49,54 ****
--- 49,55 ----
  #include "pointer-set.h"
  #include "alloc-pool.h"
  #include "tree-ssa-alias.h"
+ #include "alias-export.h"
  
  /* Broad overview of how alias analysis on gimple works:
  
*************** dump_alias_stats (FILE *s)
*** 135,140 ****
--- 136,147 ----
  	   + alias_stats.call_may_clobber_ref_p_may_alias);
  }
  
+ #define GET_PTR_INFO_FOR(PTR,EXPI) (current_ir_type () == IR_GIMPLE     \
+                                     ? SSA_NAME_PTR_INFO (PTR)           \
+                                     : (EXPI))
+ #define GET_ESCAPED_SOLUTION(EXES) (current_ir_type () == IR_GIMPLE     \
+                                     ? &cfun->gimple_df->escaped         \
+                                     : (EXES))
  
  /* Return true, if dereferencing PTR may alias with a global variable.  */
  
*************** ptr_deref_may_alias_global_p (tree ptr)
*** 161,167 ****
  /* Return true if dereferencing PTR may alias DECL.  */
  
  static bool
! ptr_deref_may_alias_decl_p (tree ptr, tree decl)
  {
    struct ptr_info_def *pi;
  
--- 168,175 ----
  /* Return true if dereferencing PTR may alias DECL.  */
  
  static bool
! ptr_deref_may_alias_decl_p (tree ptr, tree decl, struct ptr_info_def *expi,
!                             struct pt_solution *exescaped)
  {
    struct ptr_info_def *pi;
  
*************** ptr_deref_may_alias_decl_p (tree ptr, tr
*** 172,181 ****
        || TREE_CODE (ptr) == INTEGER_CST)
      return true;
  
!   gcc_assert (TREE_CODE (ptr) == SSA_NAME
! 	      && (TREE_CODE (decl) == VAR_DECL
! 		  || TREE_CODE (decl) == PARM_DECL
! 		  || TREE_CODE (decl) == RESULT_DECL));
  
    /* Non-aliased variables can not be pointed to.  */
    if (!may_be_aliased (decl))
--- 180,190 ----
        || TREE_CODE (ptr) == INTEGER_CST)
      return true;
  
!   gcc_assert ((TREE_CODE (ptr) == SSA_NAME
!                && (TREE_CODE (decl) == VAR_DECL
!                    || TREE_CODE (decl) == PARM_DECL
!                    || TREE_CODE (decl) == RESULT_DECL))
!               || current_ir_type () != IR_GIMPLE);
  
    /* Non-aliased variables can not be pointed to.  */
    if (!may_be_aliased (decl))
*************** ptr_deref_may_alias_decl_p (tree ptr, tr
*** 183,199 ****
  
    /* 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;
  
!   return pt_solution_includes (&pi->pt, decl);
  }
  
  /* Return true if dereferenced PTR1 and PTR2 may alias.  */
  
  static bool
! ptr_derefs_may_alias_p (tree ptr1, tree ptr2)
  {
    struct ptr_info_def *pi1, *pi2;
  
--- 192,211 ----
  
    /* If we do not have useful points-to information for this pointer
       we cannot disambiguate anything else.  */
!   pi = GET_PTR_INFO_FOR (ptr, expi);
    if (!pi)
      return true;
  
!   return pt_solution_includes_1 (&pi->pt, decl,
!                                  GET_ESCAPED_SOLUTION (exescaped));
  }
  
  /* Return true if dereferenced PTR1 and PTR2 may alias.  */
  
  static bool
! ptr_derefs_may_alias_p (tree ptr1, tree ptr2, struct ptr_info_def *expi1,
!                         struct ptr_info_def *expi2,
!                         struct pt_solution *exescaped)
  {
    struct ptr_info_def *pi1, *pi2;
  
*************** ptr_derefs_may_alias_p (tree ptr1, tree 
*** 206,213 ****
        || TREE_CODE (ptr2) == INTEGER_CST)
      return true;
  
!   gcc_assert (TREE_CODE (ptr1) == SSA_NAME
! 	      && TREE_CODE (ptr2) == SSA_NAME);
  
    /* 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
--- 218,226 ----
        || TREE_CODE (ptr2) == INTEGER_CST)
      return true;
  
!   gcc_assert ((TREE_CODE (ptr1) == SSA_NAME
!                && TREE_CODE (ptr2) == SSA_NAME)
!               || current_ir_type () != IR_GIMPLE);
  
    /* 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
*************** ptr_derefs_may_alias_p (tree ptr1, tree 
*** 217,228 ****
  
    /* 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;
  
!   return pt_solutions_intersect (&pi1->pt, &pi2->pt);
  }
  
  /* Return true if STMT is an "escape" site from the current function.  Escape
--- 230,242 ----
  
    /* If we do not have useful points-to information for either pointer
       we cannot disambiguate anything else.  */
!   pi1 = GET_PTR_INFO_FOR (ptr1, expi1);
!   pi2 = GET_PTR_INFO_FOR (ptr2, expi2);
    if (!pi1 || !pi2)
      return true;
  
!   return pt_solutions_intersect_1 (&pi1->pt, &pi2->pt,
!                                    GET_ESCAPED_SOLUTION (exescaped));
  }
  
  /* Return true if STMT is an "escape" site from the current function.  Escape
*************** decl_refs_may_alias_p (tree base1,
*** 535,545 ****
  
  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.
--- 549,561 ----
  
  static bool
  indirect_ref_may_alias_decl_p (tree ref1, tree ptr1,
+                                struct ptr_info_def *expi1,
  			       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,
!                                struct pt_solution *exescaped)
  {
    /* If only one reference is based on a variable, they cannot alias if
       the pointer access is beyond the extent of the variable access.
*************** indirect_ref_may_alias_decl_p (tree ref1
*** 549,557 ****
    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;
--- 565,573 ----
    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, expi1, exescaped))
      return false;
!   
    /* Disambiguations that rely on strict aliasing rules follow.  */
    if (!flag_strict_aliasing)
      return true;
*************** indirect_ref_may_alias_decl_p (tree ref1
*** 598,615 ****
  
  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.  */
--- 614,634 ----
  
  static bool
  indirect_refs_may_alias_p (tree ref1, tree ptr1,
+                            struct ptr_info_def *expi1,
  			   HOST_WIDE_INT offset1, HOST_WIDE_INT max_size1,
  			   alias_set_type base1_alias_set,
  			   tree ref2, tree ptr2,
+                            struct ptr_info_def *expi2,
  			   HOST_WIDE_INT offset2, HOST_WIDE_INT max_size2,
! 			   alias_set_type base2_alias_set,
!                            struct pt_solution *exescaped)
  {
    /* 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, expi1, expi2, exescaped))
      return false;
  
    /* Disambiguations that rely on strict aliasing rules follow.  */
*************** indirect_refs_may_alias_p (tree ref1, tr
*** 652,659 ****
  
  /* 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;
--- 671,681 ----
  
  /* Return true, if the two memory references REF1 and REF2 may alias.  */
  
! bool
! refs_may_alias_p_1 (tree ref1, tree ref2,
!                     struct ptr_info_def *expi1,
!                     struct ptr_info_def *expi2,
!                     struct pt_solution *exescaped)
  {
    tree base1, base2;
    HOST_WIDE_INT offset1 = 0, offset2 = 0;
*************** refs_may_alias_p_1 (tree ref1, tree ref2
*** 661,675 ****
    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));
! 
    /* 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);
--- 683,698 ----
    HOST_WIDE_INT max_size1 = -1, max_size2 = -1;
    bool var1_p, var2_p, ind1_p, ind2_p;
  
!   gcc_assert (current_ir_type () != IR_GIMPLE
!               || ((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)));
!               
    /* 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);
*************** refs_may_alias_p_1 (tree ref1, tree ref2
*** 709,736 ****
    ind1_p = INDIRECT_REF_P (base1);
    ind2_p = INDIRECT_REF_P (base2);
    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
--- 732,763 ----
    ind1_p = INDIRECT_REF_P (base1);
    ind2_p = INDIRECT_REF_P (base2);
    if (var1_p && ind2_p)
!     return indirect_ref_may_alias_decl_p (ref2, TREE_OPERAND (base2, 0), expi2,
  					  offset2, max_size2, -1,
  					  ref1, base1,
! 					  offset1, max_size1, -1,
!                                           exescaped);
    else if (ind1_p && var2_p)
!     return indirect_ref_may_alias_decl_p (ref1, TREE_OPERAND (base1, 0), expi1,
  					  offset1, max_size1, -1,
  					  ref2, base2,
! 					  offset2, max_size2, -1,
!                                           exescaped);
    else if (ind1_p && ind2_p)
!     return indirect_refs_may_alias_p (ref1, TREE_OPERAND (base1, 0), expi1,
  				      offset1, max_size1, -1,
! 				      ref2, TREE_OPERAND (base2, 0), expi2,
! 				      offset2, max_size2, -1,
!                                       exescaped);
  
!   gcc_assert (current_ir_type () != IR_GIMPLE);
!   return true;
  }
  
  bool
  refs_may_alias_p (tree ref1, tree ref2)
  {
!   bool res = refs_may_alias_p_1 (ref1, ref2, NULL, NULL, NULL);
    if (res)
      ++alias_stats.refs_may_alias_p_may_alias;
    else
diff -cprdN -x .svn -x TAGS trunk/gcc/tree-ssa-alias.h alias-export/gcc/tree-ssa-alias.h
*** trunk/gcc/tree-ssa-alias.h	Tue Apr 28 11:40:36 2009
--- alias-export/gcc/tree-ssa-alias.h	Tue Apr 28 12:26:21 2009
*************** struct GTY(()) pt_solution
*** 78,83 ****
--- 78,85 ----
  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 refs_may_alias_p_1 (tree, tree, struct ptr_info_def *, struct ptr_info_def *,
+                                 struct pt_solution *);
  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,
*************** extern unsigned int compute_may_aliases 
*** 98,103 ****
--- 100,108 ----
  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_solution_includes_1 (struct pt_solution *, const_tree, struct pt_solution *);
+ extern bool pt_solutions_intersect_1 (struct pt_solution *, struct pt_solution *,
+                                       struct pt_solution *);
  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 *);
diff -cprdN -x .svn -x TAGS trunk/gcc/tree-ssa-loop-ivopts.c alias-export/gcc/tree-ssa-loop-ivopts.c
*** trunk/gcc/tree-ssa-loop-ivopts.c	Wed Apr  8 13:59:50 2009
--- alias-export/gcc/tree-ssa-loop-ivopts.c	Tue Apr 14 15:40:33 2009
*************** along with GCC; see the file COPYING3.  
*** 91,96 ****
--- 91,97 ----
  #include "params.h"
  #include "langhooks.h"
  #include "tree-affine.h"
+ #include "alias-export.h"
  #include "target.h"
  
  /* The infinite cost.  */
*************** copy_ref_info (tree new_ref, tree old_re
*** 5230,5236 ****
    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);
  }
  
  /* Rewrites USE (address that is an iv) using candidate CAND.  */
--- 5231,5244 ----
    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);
!       /* As MEM_ORIG_EXPR binds MEM to TMR_ORIGINAL of TARGET_MEM_REF it was
!          produced from, we need to change all occurences of OLD_REF to
!          TMR_ORIGINAL (NEW_REF) in exported data.  */
!       if (flag_ddg_export)
!         replace_var_in_datarefs (old_ref, TMR_ORIGINAL (new_ref));
!     }
  }
  
  /* Rewrites USE (address that is an iv) using candidate CAND.  */
diff -cprdN -x .svn -x TAGS trunk/gcc/tree-ssa-structalias.c alias-export/gcc/tree-ssa-structalias.c
*** trunk/gcc/tree-ssa-structalias.c	Wed May 13 10:45:32 2009
--- alias-export/gcc/tree-ssa-structalias.c	Wed May 13 11:21:38 2009
*************** pt_solution_includes_global (struct pt_s
*** 4975,4982 ****
  /* Return true if the points-to solution *PT includes the variable
     declaration DECL.  */
  
! static bool
! pt_solution_includes_1 (struct pt_solution *pt, const_tree decl)
  {
    if (pt->anything)
      return true;
--- 4975,4983 ----
  /* Return true if the points-to solution *PT includes the variable
     declaration DECL.  */
  
! bool
! pt_solution_includes_1 (struct pt_solution *pt, const_tree decl,
!                         struct pt_solution *escaped)
  {
    if (pt->anything)
      return true;
*************** pt_solution_includes_1 (struct pt_soluti
*** 4991,4997 ****
  
    /* If the solution includes ESCAPED, check it.  */
    if (pt->escaped
!       && pt_solution_includes_1 (&cfun->gimple_df->escaped, decl))
      return true;
  
    return false;
--- 4992,4998 ----
  
    /* If the solution includes ESCAPED, check it.  */
    if (pt->escaped
!       && pt_solution_includes_1 (escaped, decl, escaped))
      return true;
  
    return false;
*************** pt_solution_includes_1 (struct pt_soluti
*** 5000,5006 ****
  bool
  pt_solution_includes (struct pt_solution *pt, const_tree decl)
  {
!   bool res = pt_solution_includes_1 (pt, decl);
    if (res)
      ++pta_stats.pt_solution_includes_may_alias;
    else
--- 5001,5007 ----
  bool
  pt_solution_includes (struct pt_solution *pt, const_tree decl)
  {
!   bool res = pt_solution_includes_1 (pt, decl, &cfun->gimple_df->escaped);
    if (res)
      ++pta_stats.pt_solution_includes_may_alias;
    else
*************** pt_solution_includes (struct pt_solution
*** 5011,5018 ****
  /* Return true if both points-to solutions PT1 and PT2 have a non-empty
     intersection.  */
  
! static bool
! pt_solutions_intersect_1 (struct pt_solution *pt1, struct pt_solution *pt2)
  {
    if (pt1->anything || pt2->anything)
      return true;
--- 5012,5020 ----
  /* Return true if both points-to solutions PT1 and PT2 have a non-empty
     intersection.  */
  
! bool
! pt_solutions_intersect_1 (struct pt_solution *pt1, struct pt_solution *pt2,
!                           struct pt_solution *escaped)
  {
    if (pt1->anything || pt2->anything)
      return true;
*************** pt_solutions_intersect_1 (struct pt_solu
*** 5028,5034 ****
  
    /* 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.  */
--- 5030,5036 ----
  
    /* Check the escaped solution if required.  */
    if ((pt1->escaped || pt2->escaped)
!       && !pt_solution_empty_p (escaped))
      {
        /* If both point to escaped memory and that solution
  	 is not empty they alias.  */
*************** pt_solutions_intersect_1 (struct pt_solu
*** 5038,5046 ****
        /* 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;
      }
  
--- 5040,5048 ----
        /* If either points to escaped memory see if the escaped solution
  	 intersects with the other.  */
        if ((pt1->escaped
! 	   && pt_solutions_intersect_1 (escaped, pt2, escaped))
  	  || (pt2->escaped
! 	      && pt_solutions_intersect_1 (escaped, pt1, escaped)))
  	return true;
      }
  
*************** pt_solutions_intersect_1 (struct pt_solu
*** 5053,5059 ****
  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
--- 5055,5061 ----
  bool
  pt_solutions_intersect (struct pt_solution *pt1, struct pt_solution *pt2)
  {
!   bool res = pt_solutions_intersect_1 (pt1, pt2, &cfun->gimple_df->escaped);
    if (res)
      ++pta_stats.pt_solutions_intersect_may_alias;
    else
diff -cprdN -x .svn -x TAGS trunk/gcc/tree-ssa-uncprop.c alias-export/gcc/tree-ssa-uncprop.c
*** trunk/gcc/tree-ssa-uncprop.c	Wed May  6 17:32:34 2009
--- alias-export/gcc/tree-ssa-uncprop.c	Tue Apr 28 14:36:20 2009
*************** struct gimple_opt_pass pass_uncprop = 
*** 606,612 ****
    0,					/* properties_provided */
    0,					/* properties_destroyed */
    0,					/* todo_flags_start */
!   TODO_dump_func | TODO_verify_ssa	/* todo_flags_finish */
   }
  };
  
--- 606,613 ----
    0,					/* properties_provided */
    0,					/* properties_destroyed */
    0,					/* todo_flags_start */
!   TODO_dump_func | TODO_verify_ssa
!   | TODO_rebuild_alias                 /* todo_flags_finish */
   }
  };
  
diff -cprdN -x .svn -x TAGS trunk/gcc/tree-ssa.c alias-export/gcc/tree-ssa.c
*** trunk/gcc/tree-ssa.c	Wed May  6 10:12:38 2009
--- alias-export/gcc/tree-ssa.c	Tue May 12 20:23:17 2009
*************** along with GCC; see the file COPYING3.  
*** 44,49 ****
--- 44,50 ----
  #include "hashtab.h"
  #include "tree-dump.h"
  #include "tree-pass.h"
+ #include "alias-export.h"
  #include "toplev.h"
  
  /* Pointer map of variable mappings, keyed by edge.  */
*************** delete_tree_ssa (void)
*** 817,823 ****
  	  SSA_NAME_IMM_USE_NODE (var).prev = &(SSA_NAME_IMM_USE_NODE (var));
  	  SSA_NAME_IMM_USE_NODE (var).next = &(SSA_NAME_IMM_USE_NODE (var));
  	}
!       release_ssa_name (var);
      }
  
    /* FIXME.  This may not be necessary.  We will release all this
--- 818,826 ----
  	  SSA_NAME_IMM_USE_NODE (var).prev = &(SSA_NAME_IMM_USE_NODE (var));
  	  SSA_NAME_IMM_USE_NODE (var).next = &(SSA_NAME_IMM_USE_NODE (var));
  	}
!       if (! var || TREE_CODE (var) != SSA_NAME
!           || ! (flag_alias_export || flag_ddg_export))
!         release_ssa_name (var);
      }
  
    /* FIXME.  This may not be necessary.  We will release all this
*************** delete_tree_ssa (void)
*** 848,853 ****
--- 851,860 ----
  	set_phi_nodes (bb, NULL);
      }
  
+   /* We need to do this while referenced_vars are still accessible.  */
+   if (flag_alias_export)
+     record_escaped_solution (&cfun->gimple_df->escaped);
+ 
    /* Remove annotations from every referenced local variable.  */
    FOR_EACH_REFERENCED_VAR (var, rvi)
      {

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]