This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH][RFC] Keep per call-stmt information about clobbers/uses
- From: Richard Guenther <richard dot guenther at gmail dot com>
- To: Richard Guenther <rguenther at suse dot de>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Mon, 12 Apr 2010 17:21:25 +0200
- Subject: Re: [PATCH][RFC] Keep per call-stmt information about clobbers/uses
- References: <alpine.LNX.2.00.0911191704480.17161@zhemvz.fhfr.qr>
On Thu, Nov 19, 2009 at 6:08 PM, Richard Guenther <rguenther@suse.de> wrote:
>
> This transitions away from using the global escaped and callused
> points-to sets for call clobber/use analysis. ?This is required
> both for IPA-PTA and for annotating calls with information about
> what arguments escape, are clobbered, etc.
>
> This first patch just does the transition to per-call information
> and should be a no-op functionality wise. ?It enlarges all call
> statements by effectively 4 pointers (well, 2 pointers and some
> flags, but as they are two struct pt_solutions we get the
> flags padded to pointer size).
>
> A followup patch making pure/const call handling context sensitive
> is already done.
>
> Bootstrapped on x86_64-unknown-linux-gnu, testing in progress,
> queued for stage1.
Applied as r158226 after re-bootstrapping and testing on
x86_64-unknown-linux-gnu.
Richard.
> Richard.
>
> 2009-11-19 ?Richard Guenther ?<rguenther@suse.de>
>
> ? ? ? ?* gsstruct.def (GSS_CALL): New.
> ? ? ? ?* gimple.def (GIMPLE_CALL): Change to GSS_CALL.
> ? ? ? ?* gimple.h: Include tree-ssa-alias.h.
> ? ? ? ?(struct gimple_statement_call): New.
> ? ? ? ?(union gimple_statement_struct_d): Add gimple_call member.
> ? ? ? ?(gimple_call_reset_alias_info): Declare.
> ? ? ? ?(gimple_call_use_set): New function.
> ? ? ? ?(gimple_call_clobber_set): Likewise.
> ? ? ? ?* Makefile.in (GIMPLE_H): Add tree-ssa-alias.h.
> ? ? ? ?* gimple.c (gimple_call_reset_alias_info): New function.
> ? ? ? ?(gimple_build_call_1): Call it.
> ? ? ? ?* lto-streamer-in.c (input_gimple_stmt): Likewise.
> ? ? ? ?* tree-inline.c (remap_gimple_stmt): Likewise.
> ? ? ? ?(expand_call_inline): Remove callused handling.
> ? ? ? ?* cfgexpand.c (update_alias_info_with_stack_vars): Likewise.
> ? ? ? ?* tree-dfa.c (dump_variable): Likewise.
> ? ? ? ?* tree-parloops.c (parallelize_loops): Likewise.
> ? ? ? ?* tree-ssa.c (init_tree_ssa): Likewise.
> ? ? ? ?(delete_tree_ssa): Likewise.
> ? ? ? ?* tree-flow-inline.h (is_call_used): Remove.
> ? ? ? ?* tree-flow.h (struct gimple_df): Remove callused member.
> ? ? ? ?* tree-nrv.c (dest_safe_for_nrv_p): Adjust predicate.
> ? ? ? ?* tree-ssa-alias.c (dump_alias_info): Remove callused handling.
> ? ? ? ?(ref_maybe_used_by_call_p_1): Simplify.
> ? ? ? ?(call_may_clobber_ref_p_1): Likewise.
> ? ? ? ?* tree-ssa-structalias.c (compute_points_to_sets): Set
> ? ? ? ?the call stmt used and clobbered sets.
> ? ? ? ?* tree-tailcall.c (suitable_for_tail_opt_p): Adjust predicate.
> ? ? ? ?(find_tail_calls): Verify the tail call.
>
> Index: trunk/gcc/gimple.def
> ===================================================================
> *** trunk.orig/gcc/gimple.def ? 2009-11-18 15:54:37.000000000 +0100
> --- trunk/gcc/gimple.def ? ? ? ?2009-11-19 12:08:35.000000000 +0100
> *************** DEFGSCODE(GIMPLE_ASM, "gimple_asm", GSS_
> *** 122,128 ****
> ? ? is_gimple_operand.
>
> ? ? ?CHAIN is the optional static chain link for nested functions. ?*/
> ! DEFGSCODE(GIMPLE_CALL, "gimple_call", GSS_WITH_MEM_OPS)
>
> ?/* GIMPLE_RETURN <RETVAL> represents return statements.
>
> --- 122,128 ----
> ? ? is_gimple_operand.
>
> ? ? ?CHAIN is the optional static chain link for nested functions. ?*/
> ! DEFGSCODE(GIMPLE_CALL, "gimple_call", GSS_CALL)
>
> ?/* GIMPLE_RETURN <RETVAL> represents return statements.
>
> Index: trunk/gcc/gimple.h
> ===================================================================
> *** trunk.orig/gcc/gimple.h ? ? 2009-11-18 15:54:17.000000000 +0100
> --- trunk/gcc/gimple.h ?2009-11-19 13:14:16.000000000 +0100
> *************** along with GCC; see the file COPYING3.
> *** 29,34 ****
> --- 29,35 ----
> ?#include "hard-reg-set.h"
> ?#include "basic-block.h"
> ?#include "tree-ssa-operands.h"
> + #include "tree-ssa-alias.h"
>
> ?DEF_VEC_P(gimple);
> ?DEF_VEC_ALLOC_P(gimple,heap);
> *************** struct GTY(()) gimple_statement_with_mem
> *** 390,395 ****
> --- 391,415 ----
> ?};
>
>
> + /* Call statements that take both memory and register operands. ?*/
> +
> + struct GTY(()) gimple_statement_call
> + {
> + ? /* [ WORD 1-8 ] ?*/
> + ? struct gimple_statement_with_memory_ops_base membase;
> +
> + ? /* [ WORD 9-12 ] ?*/
> + ? struct pt_solution call_used;
> + ? struct pt_solution call_clobbered;
> +
> + ? /* [ WORD 13 ]
> + ? ? ?Operand vector. ?NOTE! ?This must always be the last field
> + ? ? ?of this structure. ?In particular, this means that this
> + ? ? ?structure cannot be embedded inside another one. ?*/
> + ? tree GTY((length ("%h.membase.opbase.gsbase.num_ops"))) op[1];
> + };
> +
> +
> ?/* OpenMP statements (#pragma omp). ?*/
>
> ?struct GTY(()) gimple_statement_omp {
> *************** union GTY ((desc ("gimple_statement_stru
> *** 739,744 ****
> --- 759,765 ----
> ? ?struct gimple_statement_with_ops GTY ((tag ("GSS_WITH_OPS"))) gsops;
> ? ?struct gimple_statement_with_memory_ops_base GTY ((tag ("GSS_WITH_MEM_OPS_BASE"))) gsmembase;
> ? ?struct gimple_statement_with_memory_ops GTY ((tag ("GSS_WITH_MEM_OPS"))) gsmem;
> + ? struct gimple_statement_call GTY ((tag ("GSS_CALL"))) gimple_call;
> ? ?struct gimple_statement_omp GTY ((tag ("GSS_OMP"))) omp;
> ? ?struct gimple_statement_bind GTY ((tag ("GSS_BIND"))) gimple_bind;
> ? ?struct gimple_statement_catch GTY ((tag ("GSS_CATCH"))) gimple_catch;
> *************** void gimple_seq_free (gimple_seq);
> *** 832,837 ****
> --- 853,859 ----
> ?void gimple_seq_add_seq (gimple_seq *, gimple_seq);
> ?gimple_seq gimple_seq_copy (gimple_seq);
> ?int gimple_call_flags (const_gimple);
> + void gimple_call_reset_alias_info (gimple);
> ?bool gimple_assign_copy_p (gimple);
> ?bool gimple_assign_ssa_name_copy_p (gimple);
> ?bool gimple_assign_single_p (gimple);
> *************** gimple_call_copy_flags (gimple dest_call
> *** 2214,2219 ****
> --- 2236,2263 ----
> ?}
>
>
> + /* Return a pointer to the points-to solution for the set of call-used
> + ? ?variables of the call CALL. ?*/
> +
> + static inline struct pt_solution *
> + gimple_call_use_set (gimple call)
> + {
> + ? GIMPLE_CHECK (call, GIMPLE_CALL);
> + ? return &call->gimple_call.call_used;
> + }
> +
> +
> + /* Return a pointer to the points-to solution for the set of call-used
> + ? ?variables of the call CALL. ?*/
> +
> + static inline struct pt_solution *
> + gimple_call_clobber_set (gimple call)
> + {
> + ? GIMPLE_CHECK (call, GIMPLE_CALL);
> + ? return &call->gimple_call.call_clobbered;
> + }
> +
> +
> ?/* Returns true if this is a GIMPLE_ASSIGN or a GIMPLE_CALL with a
> ? ? non-NULL lhs. ?*/
>
> Index: trunk/gcc/gsstruct.def
> ===================================================================
> *** trunk.orig/gcc/gsstruct.def 2009-11-18 15:54:23.000000000 +0100
> --- trunk/gcc/gsstruct.def ? ? ?2009-11-19 12:09:03.000000000 +0100
> *************** DEFGSSTRUCT(GSS_BASE, gimple_statement_b
> *** 29,34 ****
> --- 29,35 ----
> ?DEFGSSTRUCT(GSS_WITH_OPS, gimple_statement_with_ops, true)
> ?DEFGSSTRUCT(GSS_WITH_MEM_OPS_BASE, gimple_statement_with_memory_ops_base, false)
> ?DEFGSSTRUCT(GSS_WITH_MEM_OPS, gimple_statement_with_memory_ops, true)
> + DEFGSSTRUCT(GSS_CALL, gimple_statement_call, true)
> ?DEFGSSTRUCT(GSS_ASM, gimple_statement_asm, true)
> ?DEFGSSTRUCT(GSS_BIND, gimple_statement_bind, false)
> ?DEFGSSTRUCT(GSS_PHI, gimple_statement_phi, false)
> Index: trunk/gcc/Makefile.in
> ===================================================================
> *** trunk.orig/gcc/Makefile.in ?2009-11-17 16:12:38.000000000 +0100
> --- trunk/gcc/Makefile.in ? ? ? 2009-11-19 12:49:39.000000000 +0100
> *************** BASIC_BLOCK_H = basic-block.h $(BITMAP_H
> *** 859,865 ****
> ? ? ? ? ? ?hard-reg-set.h $(PREDICT_H) vec.h $(FUNCTION_H) \
> ? ? ? ? ? ?cfghooks.h $(OBSTACK_H)
> ?GIMPLE_H = gimple.h gimple.def gsstruct.def pointer-set.h vec.h \
> ! ? ? ? $(GGC_H) $(BASIC_BLOCK_H) $(TM_H) $(TARGET_H) tree-ssa-operands.h
> ?GCOV_IO_H = gcov-io.h gcov-iov.h auto-host.h
> ?COVERAGE_H = coverage.h $(GCOV_IO_H)
> ?DEMANGLE_H = $(srcdir)/../include/demangle.h
> --- 859,866 ----
> ? ? ? ? ? ?hard-reg-set.h $(PREDICT_H) vec.h $(FUNCTION_H) \
> ? ? ? ? ? ?cfghooks.h $(OBSTACK_H)
> ?GIMPLE_H = gimple.h gimple.def gsstruct.def pointer-set.h vec.h \
> ! ? ? ? $(GGC_H) $(BASIC_BLOCK_H) $(TM_H) $(TARGET_H) tree-ssa-operands.h \
> ! ? ? ? tree-ssa-alias.h
> ?GCOV_IO_H = gcov-io.h gcov-iov.h auto-host.h
> ?COVERAGE_H = coverage.h $(GCOV_IO_H)
> ?DEMANGLE_H = $(srcdir)/../include/demangle.h
> Index: trunk/gcc/cfgexpand.c
> ===================================================================
> *** trunk.orig/gcc/cfgexpand.c ?2009-11-18 12:49:55.000000000 +0100
> --- trunk/gcc/cfgexpand.c ? ? ? 2009-11-19 13:55:35.000000000 +0100
> *************** update_alias_info_with_stack_vars (void)
> *** 591,598 ****
>
> ? ? ? ?add_partitioned_vars_to_ptset (&cfun->gimple_df->escaped,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? decls_to_partitions, visited, temp);
> - ? ? ? add_partitioned_vars_to_ptset (&cfun->gimple_df->callused,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?decls_to_partitions, visited, temp);
>
> ? ? ? ?pointer_set_destroy (visited);
> ? ? ? ?pointer_map_destroy (decls_to_partitions);
> --- 591,596 ----
> Index: trunk/gcc/gimple.c
> ===================================================================
> *** trunk.orig/gcc/gimple.c ? ? 2009-11-18 15:53:50.000000000 +0100
> --- trunk/gcc/gimple.c ?2009-11-19 13:13:16.000000000 +0100
> *************** gimple_build_return (tree retval)
> *** 198,203 ****
> --- 198,218 ----
> ? ?return s;
> ?}
>
> + /* Reset alias information on call S. ?*/
> +
> + void
> + gimple_call_reset_alias_info (gimple s)
> + {
> + ? if (gimple_call_flags (s) & ECF_CONST)
> + ? ? memset (gimple_call_use_set (s), 0, sizeof (struct pt_solution));
> + ? else
> + ? ? pt_solution_reset (gimple_call_use_set (s));
> + ? if (gimple_call_flags (s) & (ECF_CONST|ECF_PURE|ECF_NOVOPS))
> + ? ? memset (gimple_call_clobber_set (s), 0, sizeof (struct pt_solution));
> + ? else
> + ? ? pt_solution_reset (gimple_call_clobber_set (s));
> + }
> +
> ?/* Helper for gimple_build_call, gimple_build_call_vec and
> ? ? gimple_build_call_from_tree. ?Build the basic components of a
> ? ? GIMPLE_CALL statement to function FN with NARGS arguments. ?*/
> *************** gimple_build_call_1 (tree fn, unsigned n
> *** 209,214 ****
> --- 224,230 ----
> ? ?if (TREE_CODE (fn) == FUNCTION_DECL)
> ? ? ?fn = build_fold_addr_expr (fn);
> ? ?gimple_set_op (s, 1, fn);
> + ? gimple_call_reset_alias_info (s);
> ? ?return s;
> ?}
>
> Index: trunk/gcc/lto-streamer-in.c
> ===================================================================
> *** trunk.orig/gcc/lto-streamer-in.c ? ?2009-11-18 12:33:52.000000000 +0100
> --- trunk/gcc/lto-streamer-in.c 2009-11-19 12:46:29.000000000 +0100
> *************** input_gimple_stmt (struct lto_input_bloc
> *** 1136,1141 ****
> --- 1136,1145 ----
> ? ? ? ?}
> ? ? ?}
>
> + ? /* Reset alias information. ?*/
> + ? if (code == GIMPLE_CALL)
> + ? ? gimple_call_reset_alias_info (stmt);
> +
> ? ?/* Fixup reference tree operands for substituted prevailing decls
> ? ? ? with mismatched types. ?*/
> ? ?maybe_fixup_decls (stmt);
> Index: trunk/gcc/tree-dfa.c
> ===================================================================
> *** trunk.orig/gcc/tree-dfa.c ? 2009-11-18 12:49:55.000000000 +0100
> --- trunk/gcc/tree-dfa.c ? ? ? ?2009-11-19 14:11:31.000000000 +0100
> *************** dump_variable (FILE *file, tree var)
> *** 302,309 ****
>
> ? ?if (is_call_clobbered (var))
> ? ? ?fprintf (file, ", call clobbered");
> - ? else if (is_call_used (var))
> - ? ? fprintf (file, ", call used");
>
> ? ?if (ann && ann->noalias_state == NO_ALIAS)
> ? ? ?fprintf (file, ", NO_ALIAS (does not alias other NO_ALIAS symbols)");
> --- 302,307 ----
> Index: trunk/gcc/tree-flow-inline.h
> ===================================================================
> *** trunk.orig/gcc/tree-flow-inline.h ? 2009-09-15 16:51:21.000000000 +0200
> --- trunk/gcc/tree-flow-inline.h ? ? ? ?2009-11-19 14:12:31.000000000 +0100
> *************** is_call_clobbered (const_tree var)
> *** 669,683 ****
> ? ? ? ? ? ? ?&& pt_solution_includes (&cfun->gimple_df->escaped, var)));
> ?}
>
> - /* Return true if VAR is used by function calls. ?*/
> - static inline bool
> - is_call_used (const_tree var)
> - {
> - ? return (is_call_clobbered (var)
> - ? ? ? ? || (may_be_aliased (var)
> - ? ? ? ? ? ? && pt_solution_includes (&cfun->gimple_df->callused, var)));
> - }
> -
> ?/* Return the common annotation for T. ?Return NULL if the annotation
> ? ? doesn't already exist. ?*/
> ?static inline tree_ann_common_t
> --- 669,674 ----
> Index: trunk/gcc/tree-flow.h
> ===================================================================
> *** trunk.orig/gcc/tree-flow.h ?2009-11-18 12:49:55.000000000 +0100
> --- trunk/gcc/tree-flow.h ? ? ? 2009-11-19 13:54:38.000000000 +0100
> *************** struct GTY(()) gimple_df {
> *** 60,68 ****
> ? ?/* The PTA solution for the ESCAPED artificial variable. ?*/
> ? ?struct pt_solution escaped;
>
> - ? /* The PTA solution for the CALLUSED artificial variable. ?*/
> - ? struct pt_solution callused;
> -
> ? ?/* A map of decls to artificial ssa-names that point to the partition
> ? ? ? of the decl. ?*/
> ? ?struct pointer_map_t * GTY((skip(""))) decls_to_pointers;
> --- 60,65 ----
> Index: trunk/gcc/tree-inline.c
> ===================================================================
> *** trunk.orig/gcc/tree-inline.c ? ? ? ?2009-11-18 12:49:55.000000000 +0100
> --- trunk/gcc/tree-inline.c ? ? 2009-11-19 13:56:11.000000000 +0100
> *************** remap_gimple_stmt (gimple stmt, copy_bod
> *** 1401,1406 ****
> --- 1401,1413 ----
> ? ? ? ? ? ? ? ? ?default:
> ? ? ? ? ? ? ? ? ? ?break;
> ? ? ? ? ? ? ? ? ?}
> +
> + ? ? ? ? ? ? /* Reset alias info.
> + ? ? ? ? ? ? ? ???? ?By maintaining DECL_PT_UID this should not
> + ? ? ? ? ? ? ? ?be necessary, but the plan is to only maintain
> + ? ? ? ? ? ? ? ?it when IPA-PTA was run. ?It's not too easy to
> + ? ? ? ? ? ? ? ?detect this here ... ?*/
> + ? ? ? ? ? ? gimple_call_reset_alias_info (copy);
> ? ? ? ? ? ?}
> ? ? ? ? ? ?break;
>
> *************** expand_call_inline (basic_block bb, gimp
> *** 3761,3772 ****
> ? ? ? ? ? ? cg_edge->frequency * REG_BR_PROB_BASE / CGRAPH_FREQ_BASE,
> ? ? ? ? ? ? bb, return_block);
>
> ! ? /* Reset the escaped and callused solutions. ?*/
> ? ?if (cfun->gimple_df)
> ! ? ? {
> ! ? ? ? pt_solution_reset (&cfun->gimple_df->escaped);
> ! ? ? ? pt_solution_reset (&cfun->gimple_df->callused);
> ! ? ? }
>
> ? ?/* Clean up. ?*/
> ? ?if (id->debug_map)
> --- 3768,3776 ----
> ? ? ? ? ? ? cg_edge->frequency * REG_BR_PROB_BASE / CGRAPH_FREQ_BASE,
> ? ? ? ? ? ? bb, return_block);
>
> ! ? /* Reset the escaped solution. ?*/
> ? ?if (cfun->gimple_df)
> ! ? ? pt_solution_reset (&cfun->gimple_df->escaped);
>
> ? ?/* Clean up. ?*/
> ? ?if (id->debug_map)
> Index: trunk/gcc/tree-nrv.c
> ===================================================================
> *** trunk.orig/gcc/tree-nrv.c ? 2009-05-11 14:17:29.000000000 +0200
> --- trunk/gcc/tree-nrv.c ? ? ? ?2009-11-19 14:12:19.000000000 +0100
> *************** dest_safe_for_nrv_p (tree dest)
> *** 301,307 ****
> ? ?if (TREE_CODE (dest) == SSA_NAME)
> ? ? ?dest = SSA_NAME_VAR (dest);
>
> ! ? if (is_call_used (dest))
> ? ? ?return false;
>
> ? ?return true;
> --- 301,307 ----
> ? ?if (TREE_CODE (dest) == SSA_NAME)
> ? ? ?dest = SSA_NAME_VAR (dest);
>
> ! ? if (is_call_clobbered (dest))
> ? ? ?return false;
>
> ? ?return true;
> Index: trunk/gcc/tree-parloops.c
> ===================================================================
> *** trunk.orig/gcc/tree-parloops.c ? ? ?2009-10-22 17:35:05.000000000 +0200
> --- trunk/gcc/tree-parloops.c ? 2009-11-19 13:56:02.000000000 +0100
> *************** parallelize_loops (void)
> *** 1972,1984 ****
> ? ?htab_delete (reduction_list);
>
> ? ?/* Parallelization will cause new function calls to be inserted through
> ! ? ? ?which local variables will escape. ?Reset the points-to solutions
> ! ? ? ?for ESCAPED and CALLUSED. ?*/
> ? ?if (changed)
> ! ? ? {
> ! ? ? ? pt_solution_reset (&cfun->gimple_df->escaped);
> ! ? ? ? pt_solution_reset (&cfun->gimple_df->callused);
> ! ? ? }
>
> ? ?return changed;
> ?}
> --- 1972,1981 ----
> ? ?htab_delete (reduction_list);
>
> ? ?/* Parallelization will cause new function calls to be inserted through
> ! ? ? ?which local variables will escape. ?Reset the points-to solution
> ! ? ? ?for ESCAPED. ?*/
> ? ?if (changed)
> ! ? ? pt_solution_reset (&cfun->gimple_df->escaped);
>
> ? ?return changed;
> ?}
> Index: trunk/gcc/tree-ssa-alias.c
> ===================================================================
> *** trunk.orig/gcc/tree-ssa-alias.c ? ? 2009-11-18 15:53:50.000000000 +0100
> --- trunk/gcc/tree-ssa-alias.c ?2009-11-19 13:56:28.000000000 +0100
> *************** dump_alias_info (FILE *file)
> *** 336,343 ****
>
> ? ?fprintf (file, "\nESCAPED");
> ? ?dump_points_to_solution (file, &cfun->gimple_df->escaped);
> - ? fprintf (file, "\nCALLUSED");
> - ? dump_points_to_solution (file, &cfun->gimple_df->callused);
>
> ? ?fprintf (file, "\n\nFlow-insensitive points-to information\n\n");
>
> --- 336,341 ----
> *************** ref_maybe_used_by_call_p_1 (gimple call,
> *** 1006,1056 ****
> ? ? ? ?goto process_args;
> ? ? ?}
>
> ! ? /* If the base variable is call-used or call-clobbered then
> ! ? ? ?it may be used. ?*/
> ! ? if (flags & (ECF_PURE|ECF_CONST|ECF_LOOPING_CONST_OR_PURE|ECF_NOVOPS))
> ? ? ?{
> ! ? ? ? if (DECL_P (base))
> ! ? ? ? {
> ! ? ? ? ? if (is_call_used (base))
> ! ? ? ? ? ? return true;
> ! ? ? ? }
> ! ? ? ? else if (INDIRECT_REF_P (base)
> ! ? ? ? ? ? ? ?&& TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
> ! ? ? ? {
> ! ? ? ? ? struct ptr_info_def *pi = SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0));
> ! ? ? ? ? if (!pi)
> ! ? ? ? ? ? return true;
> !
> ! ? ? ? ? if (pt_solution_includes_global (&pi->pt)
> ! ? ? ? ? ? ? || pt_solutions_intersect (&cfun->gimple_df->callused, &pi->pt)
> ! ? ? ? ? ? ? || pt_solutions_intersect (&cfun->gimple_df->escaped, &pi->pt))
> ! ? ? ? ? ? return true;
> ! ? ? ? }
> ! ? ? ? else
> ? ? ? ?return true;
> ? ? ?}
> ! ? else
> ? ? ?{
> ! ? ? ? if (DECL_P (base))
> ! ? ? ? {
> ! ? ? ? ? if (is_call_clobbered (base))
> ! ? ? ? ? ? return true;
> ! ? ? ? }
> ! ? ? ? else if (INDIRECT_REF_P (base)
> ! ? ? ? ? ? ? ?&& TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
> ! ? ? ? {
> ! ? ? ? ? struct ptr_info_def *pi = SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0));
> ! ? ? ? ? if (!pi)
> ! ? ? ? ? ? return true;
>
> ! ? ? ? ? if (pt_solution_includes_global (&pi->pt)
> ! ? ? ? ? ? ? || pt_solutions_intersect (&cfun->gimple_df->escaped, &pi->pt))
> ! ? ? ? ? ? return true;
> ! ? ? ? }
> ! ? ? ? else
> ? ? ? ?return true;
> ? ? ?}
>
> ? ?/* Inspect call arguments for passed-by-value aliases. ?*/
> ?process_args:
> --- 1004,1027 ----
> ? ? ? ?goto process_args;
> ? ? ?}
>
> ! ? /* Check if the base variable is call-used. ?*/
> ! ? if (DECL_P (base))
> ? ? ?{
> ! ? ? ? if (pt_solution_includes (gimple_call_use_set (call), base))
> ? ? ? ?return true;
> ? ? ?}
> ! ? else if (INDIRECT_REF_P (base)
> ! ? ? ? ? ?&& TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
> ? ? ?{
> ! ? ? ? struct ptr_info_def *pi = SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0));
> ! ? ? ? if (!pi)
> ! ? ? ? return true;
>
> ! ? ? ? if (pt_solutions_intersect (gimple_call_use_set (call), &pi->pt))
> ? ? ? ?return true;
> ? ? ?}
> + ? else
> + ? ? return true;
>
> ? ?/* Inspect call arguments for passed-by-value aliases. ?*/
> ?process_args:
> *************** call_may_clobber_ref_p_1 (gimple call, a
> *** 1261,1268 ****
> ? ? ? ?return false;
> ? ? ?}
>
> ? ?if (DECL_P (base))
> ! ? ? return is_call_clobbered (base);
> ? ?else if (INDIRECT_REF_P (base)
> ? ? ? ? ? && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
> ? ? ?{
> --- 1232,1240 ----
> ? ? ? ?return false;
> ? ? ?}
>
> + ? /* Check if the base variable is call-clobbered. ?*/
> ? ?if (DECL_P (base))
> ! ? ? return pt_solution_includes (gimple_call_clobber_set (call), base);
> ? ?else if (INDIRECT_REF_P (base)
> ? ? ? ? ? && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
> ? ? ?{
> *************** call_may_clobber_ref_p_1 (gimple call, a
> *** 1270,1277 ****
> ? ? ? ?if (!pi)
> ? ? ? ?return true;
>
> ! ? ? ? return (pt_solution_includes_global (&pi->pt)
> ! ? ? ? ? ? ? || pt_solutions_intersect (&cfun->gimple_df->escaped, &pi->pt));
> ? ? ?}
>
> ? ?return true;
> --- 1242,1248 ----
> ? ? ? ?if (!pi)
> ? ? ? ?return true;
>
> ! ? ? ? return pt_solutions_intersect (gimple_call_clobber_set (call), &pi->pt);
> ? ? ?}
>
> ? ?return true;
> Index: trunk/gcc/tree-ssa-structalias.c
> ===================================================================
> *** trunk.orig/gcc/tree-ssa-structalias.c ? ? ? 2009-11-18 15:53:50.000000000 +0100
> --- trunk/gcc/tree-ssa-structalias.c ? ?2009-11-19 13:55:23.000000000 +0100
> *************** compute_points_to_sets (void)
> *** 5478,5483 ****
> --- 5478,5484 ----
> ? ?basic_block bb;
> ? ?unsigned i;
> ? ?varinfo_t vi;
> + ? struct pt_solution callused;
>
> ? ?timevar_push (TV_TREE_PTA);
>
> *************** compute_points_to_sets (void)
> *** 5514,5521 ****
> ? ? ? call-clobber analysis. ?*/
> ? ?find_what_var_points_to (get_varinfo (escaped_id),
> ? ? ? ? ? ? ? ? ? ? ? ? ? &cfun->gimple_df->escaped);
> ! ? find_what_var_points_to (get_varinfo (callused_id),
> ! ? ? ? ? ? ? ? ? ? ? ? ? ?&cfun->gimple_df->callused);
>
> ? ?/* Make sure the ESCAPED solution (which is used as placeholder in
> ? ? ? other solutions) does not reference itself. ?This simplifies
> --- 5515,5521 ----
> ? ? ? call-clobber analysis. ?*/
> ? ?find_what_var_points_to (get_varinfo (escaped_id),
> ? ? ? ? ? ? ? ? ? ? ? ? ? &cfun->gimple_df->escaped);
> ! ? find_what_var_points_to (get_varinfo (callused_id), &callused);
>
> ? ?/* Make sure the ESCAPED solution (which is used as placeholder in
> ? ? ? other solutions) does not reference itself. ?This simplifies
> *************** compute_points_to_sets (void)
> *** 5539,5544 ****
> --- 5539,5586 ----
> ? ? ? ?find_what_p_points_to (ptr);
> ? ? ?}
>
> + ? /* Compute the call-used/clobbered sets. ?*/
> + ? FOR_EACH_BB (bb)
> + ? ? {
> + ? ? ? gimple_stmt_iterator gsi;
> +
> + ? ? ? for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
> + ? ? ? {
> + ? ? ? ? gimple stmt = gsi_stmt (gsi);
> + ? ? ? ? struct pt_solution *pt;
> + ? ? ? ? if (!is_gimple_call (stmt))
> + ? ? ? ? ? continue;
> +
> + ? ? ? ? pt = gimple_call_use_set (stmt);
> + ? ? ? ? if (gimple_call_flags (stmt) & ECF_CONST)
> + ? ? ? ? ? memset (pt, 0, sizeof (struct pt_solution));
> + ? ? ? ? else if (gimple_call_flags (stmt) & ECF_PURE)
> + ? ? ? ? ? {
> + ? ? ? ? ? ? /* For const calls we should now be able to compute the
> + ? ? ? ? ? ? ? ?call-used set per function. ?*/
> + ? ? ? ? ? ? *pt = callused;
> + ? ? ? ? ? ? /* ??? ?ESCAPED can be empty even though NONLOCAL
> + ? ? ? ? ? ? ? ?always escaped. ?*/
> + ? ? ? ? ? ? pt->nonlocal = 1;
> + ? ? ? ? ? ? pt->escaped = 1;
> + ? ? ? ? ? }
> + ? ? ? ? else
> + ? ? ? ? ? {
> + ? ? ? ? ? ? *pt = cfun->gimple_df->escaped;
> + ? ? ? ? ? ? pt->nonlocal = 1;
> + ? ? ? ? ? }
> +
> + ? ? ? ? pt = gimple_call_clobber_set (stmt);
> + ? ? ? ? if (gimple_call_flags (stmt) & (ECF_CONST|ECF_PURE|ECF_NOVOPS))
> + ? ? ? ? ? memset (pt, 0, sizeof (struct pt_solution));
> + ? ? ? ? else
> + ? ? ? ? ? {
> + ? ? ? ? ? ? *pt = cfun->gimple_df->escaped;
> + ? ? ? ? ? ? pt->nonlocal = 1;
> + ? ? ? ? ? }
> + ? ? ? }
> + ? ? }
> +
> ? ?timevar_pop (TV_TREE_PTA);
> ?}
>
> Index: trunk/gcc/tree-ssa.c
> ===================================================================
> *** trunk.orig/gcc/tree-ssa.c ? 2009-11-18 12:49:55.000000000 +0100
> --- trunk/gcc/tree-ssa.c ? ? ? ?2009-11-19 13:57:16.000000000 +0100
> *************** init_tree_ssa (struct function *fn)
> *** 1112,1118 ****
> ? ?fn->gimple_df->default_defs = htab_create_ggc (20, uid_ssaname_map_hash,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? uid_ssaname_map_eq, NULL);
> ? ?pt_solution_reset (&fn->gimple_df->escaped);
> - ? pt_solution_reset (&fn->gimple_df->callused);
> ? ?init_ssanames (fn, 0);
> ? ?init_phinodes ();
> ?}
> --- 1112,1117 ----
> *************** delete_tree_ssa (void)
> *** 1150,1156 ****
> ? ?htab_delete (cfun->gimple_df->default_defs);
> ? ?cfun->gimple_df->default_defs = NULL;
> ? ?pt_solution_reset (&cfun->gimple_df->escaped);
> - ? pt_solution_reset (&cfun->gimple_df->callused);
> ? ?if (cfun->gimple_df->decls_to_pointers != NULL)
> ? ? ?pointer_map_destroy (cfun->gimple_df->decls_to_pointers);
> ? ?cfun->gimple_df->decls_to_pointers = NULL;
> --- 1149,1154 ----
> Index: trunk/gcc/tree-tailcall.c
> ===================================================================
> *** trunk.orig/gcc/tree-tailcall.c ? ? ?2009-09-22 10:27:45.000000000 +0200
> --- trunk/gcc/tree-tailcall.c ? 2009-11-19 14:42:47.000000000 +0100
> *************** suitable_for_tail_opt_p (void)
> *** 136,146 ****
> ? ?if (cfun->stdarg)
> ? ? ?return false;
>
> ! ? /* No local variable nor structure field should be call-used. ?*/
> ? ?FOR_EACH_REFERENCED_VAR (var, rvi)
> ? ? ?{
> ? ? ? ?if (!is_global_var (var)
> ! ? ? ? ? && is_call_used (var))
> ? ? ? ?return false;
> ? ? ?}
>
> --- 136,158 ----
> ? ?if (cfun->stdarg)
> ? ? ?return false;
>
> ! ? /* No local variable nor structure field should escape to callees. ?*/
> ? ?FOR_EACH_REFERENCED_VAR (var, rvi)
> ? ? ?{
> ? ? ? ?if (!is_global_var (var)
> ! ? ? ? ? /* ??? ?We do not have a suitable predicate for escaping to
> ! ? ? ? ? ? ?callees. ?With IPA-PTA the following might be incorrect.
> ! ? ? ? ? ? ?We want to catch
> ! ? ? ? ? ? ? ?foo {
> ! ? ? ? ? ? ? ? ?int i;
> ! ? ? ? ? ? ? ? ?bar (&i);
> ! ? ? ? ? ? ? ? ?foo ();
> ! ? ? ? ? ? ? ?}
> ! ? ? ? ? ? ?where bar might store &i somewhere and in the next
> ! ? ? ? ? ? ?recursion should not be able to tell if it got the
> ! ? ? ? ? ? ?same (with tail-recursion applied) or a different
> ! ? ? ? ? ? ?address. ?*/
> ! ? ? ? ? && is_call_clobbered (var))
> ? ? ? ?return false;
> ? ? ?}
>
> *************** find_tail_calls (basic_block bb, struct
> *** 430,436 ****
> ? ?func = gimple_call_fndecl (call);
> ? ?if (func == current_function_decl)
> ? ? ?{
> ! ? ? ? tree arg;
> ? ? ? ?for (param = DECL_ARGUMENTS (func), idx = 0;
> ? ? ? ? ? param && idx < gimple_call_num_args (call);
> ? ? ? ? ? param = TREE_CHAIN (param), idx ++)
> --- 442,450 ----
> ? ?func = gimple_call_fndecl (call);
> ? ?if (func == current_function_decl)
> ? ? ?{
> ! ? ? ? tree arg, var;
> ! ? ? ? referenced_var_iterator rvi;
> !
> ? ? ? ?for (param = DECL_ARGUMENTS (func), idx = 0;
> ? ? ? ? ? param && idx < gimple_call_num_args (call);
> ? ? ? ? ? param = TREE_CHAIN (param), idx ++)
> *************** find_tail_calls (basic_block bb, struct
> *** 460,465 ****
> --- 474,488 ----
> ? ? ? ?}
> ? ? ? ?if (idx == gimple_call_num_args (call) && !param)
> ? ? ? ?tail_recursion = true;
> +
> + ? ? ? /* Make sure the tail invocation of this function does not refer
> + ? ? ? ?to local variables. ?*/
> + ? ? ? FOR_EACH_REFERENCED_VAR (var, rvi)
> + ? ? ? {
> + ? ? ? ? if (!is_global_var (var)
> + ? ? ? ? ? ? && ref_maybe_used_by_stmt_p (call, var))
> + ? ? ? ? ? return;
> + ? ? ? }
> ? ? ?}
>
> ? ?/* Now check the statements after the call. ?None of them has virtual
>