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]

[PATCH][RFC] Keep per call-stmt information about clobbers/uses


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.

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


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