OSDN Git Service

2010-04-12 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 12 Apr 2010 15:20:48 +0000 (15:20 +0000)
committerMasaki Muranaka <monaka@monami-software.com>
Sun, 23 May 2010 00:56:47 +0000 (09:56 +0900)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@158226 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/Makefile.in
gcc/gimple.h
gcc/tree-dfa.c
gcc/tree-flow-inline.h
gcc/tree-inline.c
gcc/tree-nrv.c
gcc/tree-ssa-structalias.c
gcc/tree-tailcall.c

index 91a18dc..136ffae 100644 (file)
@@ -1,5 +1,37 @@
 2010-04-12  Richard Guenther  <rguenther@suse.de>
 
 2010-04-12  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.
+
+2010-04-12  Richard Guenther  <rguenther@suse.de>
+
        * ipa.c (cgraph_postorder): Adjust postorder to guarantee
        single-iteration always-inline inlining.
        * ipa-inline.c (cgraph_mark_inline): Do not return anything.
        * ipa.c (cgraph_postorder): Adjust postorder to guarantee
        single-iteration always-inline inlining.
        * ipa-inline.c (cgraph_mark_inline): Do not return anything.
index 99811e7..c1cec39 100644 (file)
@@ -876,7 +876,8 @@ BASIC_BLOCK_H = basic-block.h $(BITMAP_H) sbitmap.h varray.h $(PARTITION_H) \
           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 \
           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
+       $(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
 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 baa839f..9df6e92 100644 (file)
@@ -24,8 +24,6 @@ along with GCC; see the file COPYING3.  If not see
 
 #include "pointer-set.h"
 #include "vec.h"
 
 #include "pointer-set.h"
 #include "vec.h"
-#include "vecprim.h"
-#include "vecir.h"
 #include "ggc.h"
 #include "tm.h"
 #include "hard-reg-set.h"
 #include "ggc.h"
 #include "tm.h"
 #include "hard-reg-set.h"
@@ -33,6 +31,18 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-ssa-operands.h"
 #include "tree-ssa-alias.h"
 
 #include "tree-ssa-operands.h"
 #include "tree-ssa-alias.h"
 
+DEF_VEC_P(gimple);
+DEF_VEC_ALLOC_P(gimple,heap);
+DEF_VEC_ALLOC_P(gimple,gc);
+
+typedef gimple *gimple_p;
+DEF_VEC_P(gimple_p);
+DEF_VEC_ALLOC_P(gimple_p,heap);
+
+DEF_VEC_P(gimple_seq);
+DEF_VEC_ALLOC_P(gimple_seq,gc);
+DEF_VEC_ALLOC_P(gimple_seq,heap);
+
 /* For each block, the PHI nodes that need to be rewritten are stored into
    these vectors.  */
 typedef VEC(gimple, heap) *gimple_vec;
 /* For each block, the PHI nodes that need to be rewritten are stored into
    these vectors.  */
 typedef VEC(gimple, heap) *gimple_vec;
@@ -96,7 +106,6 @@ enum gf_mask {
     GF_CALL_RETURN_SLOT_OPT    = 1 << 2,
     GF_CALL_TAILCALL           = 1 << 3,
     GF_CALL_VA_ARG_PACK                = 1 << 4,
     GF_CALL_RETURN_SLOT_OPT    = 1 << 2,
     GF_CALL_TAILCALL           = 1 << 3,
     GF_CALL_VA_ARG_PACK                = 1 << 4,
-    GF_CALL_NOTHROW            = 1 << 5,
     GF_OMP_PARALLEL_COMBINED   = 1 << 0,
 
     /* True on an GIMPLE_OMP_RETURN statement if the return does not require
     GF_OMP_PARALLEL_COMBINED   = 1 << 0,
 
     /* True on an GIMPLE_OMP_RETURN statement if the return does not require
@@ -212,13 +221,6 @@ gimple_seq_empty_p (const_gimple_seq s)
 
 void gimple_seq_add_stmt (gimple_seq *, gimple);
 
 
 void gimple_seq_add_stmt (gimple_seq *, gimple);
 
-/* Link gimple statement GS to the end of the sequence *SEQ_P.  If
-   *SEQ_P is NULL, a new sequence is allocated.  This function is
-   similar to gimple_seq_add_stmt, but does not scan the operands.
-   During gimplification, we need to manipulate statement sequences
-   before the def/use vectors have been constructed.  */
-void gimplify_seq_add_stmt (gimple_seq *, gimple);
-
 /* Allocate a new sequence and initialize its first element with STMT.  */
 
 static inline gimple_seq
 /* Allocate a new sequence and initialize its first element with STMT.  */
 
 static inline gimple_seq
@@ -855,8 +857,6 @@ void gimple_seq_free (gimple_seq);
 void gimple_seq_add_seq (gimple_seq *, gimple_seq);
 gimple_seq gimple_seq_copy (gimple_seq);
 int gimple_call_flags (const_gimple);
 void gimple_seq_add_seq (gimple_seq *, gimple_seq);
 gimple_seq gimple_seq_copy (gimple_seq);
 int gimple_call_flags (const_gimple);
-int gimple_call_return_flags (const_gimple);
-int gimple_call_arg_flags (const_gimple, unsigned);
 void gimple_call_reset_alias_info (gimple);
 bool gimple_assign_copy_p (gimple);
 bool gimple_assign_ssa_name_copy_p (gimple);
 void gimple_call_reset_alias_info (gimple);
 bool gimple_assign_copy_p (gimple);
 bool gimple_assign_ssa_name_copy_p (gimple);
@@ -886,8 +886,6 @@ unsigned get_gimple_rhs_num_ops (enum tree_code);
 gimple gimple_alloc_stat (enum gimple_code, unsigned MEM_STAT_DECL);
 const char *gimple_decl_printable_name (tree, int);
 tree gimple_fold_obj_type_ref (tree, tree);
 gimple gimple_alloc_stat (enum gimple_code, unsigned MEM_STAT_DECL);
 const char *gimple_decl_printable_name (tree, int);
 tree gimple_fold_obj_type_ref (tree, tree);
-tree gimple_get_relevant_ref_binfo (tree ref, tree known_binfo);
-tree gimple_fold_obj_type_ref_known_binfo (HOST_WIDE_INT, tree);
 
 /* Returns true iff T is a valid GIMPLE statement.  */
 extern bool is_gimple_stmt (tree);
 
 /* Returns true iff T is a valid GIMPLE statement.  */
 extern bool is_gimple_stmt (tree);
@@ -944,7 +942,7 @@ extern bool is_gimple_call_addr (tree);
 extern tree get_call_expr_in (tree t);
 
 extern void recalculate_side_effects (tree);
 extern tree get_call_expr_in (tree t);
 
 extern void recalculate_side_effects (tree);
-extern bool gimple_compare_field_offset (tree, tree);
+extern bool compare_field_offset (tree, tree);
 extern tree gimple_register_type (tree);
 extern void print_gimple_types_stats (void);
 extern void free_gimple_type_tables (void);
 extern tree gimple_register_type (tree);
 extern void print_gimple_types_stats (void);
 extern void free_gimple_type_tables (void);
@@ -966,7 +964,6 @@ extern bool gimple_ior_addresses_taken (bitmap, gimple);
 extern tree create_tmp_var_raw (tree, const char *);
 extern tree create_tmp_var_name (const char *);
 extern tree create_tmp_var (tree, const char *);
 extern tree create_tmp_var_raw (tree, const char *);
 extern tree create_tmp_var_name (const char *);
 extern tree create_tmp_var (tree, const char *);
-extern tree create_tmp_reg (tree, const char *);
 extern tree get_initialized_tmp_var (tree, gimple_seq *, gimple_seq *);
 extern tree get_formal_tmp_var (tree, gimple_seq *);
 extern void declare_vars (tree, gimple, bool);
 extern tree get_initialized_tmp_var (tree, gimple_seq *, gimple_seq *);
 extern tree get_formal_tmp_var (tree, gimple_seq *);
 extern void declare_vars (tree, gimple, bool);
@@ -1038,6 +1035,8 @@ extern gimple gimple_current_bind_expr (void);
 extern VEC(gimple, heap) *gimple_bind_expr_stack (void);
 extern tree voidify_wrapper_expr (tree, tree);
 extern tree build_and_jump (tree *);
 extern VEC(gimple, heap) *gimple_bind_expr_stack (void);
 extern tree voidify_wrapper_expr (tree, tree);
 extern tree build_and_jump (tree *);
+extern tree alloc_stmt_list (void);
+extern void free_stmt_list (tree);
 extern tree force_labels_r (tree *, int *, void *);
 extern enum gimplify_status gimplify_va_arg_expr (tree *, gimple_seq *,
                                                  gimple_seq *);
 extern tree force_labels_r (tree *, int *, void *);
 extern enum gimplify_status gimplify_va_arg_expr (tree *, gimple_seq *,
                                                  gimple_seq *);
@@ -2202,19 +2201,6 @@ gimple_call_noreturn_p (gimple s)
 }
 
 
 }
 
 
-/* If NOTHROW_P is true, GIMPLE_CALL S is a call that is known to not throw
-   even if the called function can throw in other cases.  */
-
-static inline void
-gimple_call_set_nothrow (gimple s, bool nothrow_p)
-{
-  GIMPLE_CHECK (s, GIMPLE_CALL);
-  if (nothrow_p)
-    s->gsbase.subcode |= GF_CALL_NOTHROW;
-  else
-    s->gsbase.subcode &= ~GF_CALL_NOTHROW;
-}
-
 /* Return true if S is a nothrow call.  */
 
 static inline bool
 /* Return true if S is a nothrow call.  */
 
 static inline bool
@@ -4801,16 +4787,4 @@ gimple_alloc_kind (enum gimple_code code)
 
 extern void dump_gimple_statistics (void);
 
 
 extern void dump_gimple_statistics (void);
 
-/* In gimple-fold.c.  */
-void gimplify_and_update_call_from_tree (gimple_stmt_iterator *, tree);
-tree gimple_fold_builtin (gimple);
-bool fold_stmt (gimple_stmt_iterator *);
-bool fold_stmt_inplace (gimple);
-tree maybe_fold_offset_to_reference (location_t, tree, tree, tree);
-tree maybe_fold_offset_to_address (location_t, tree, tree, tree);
-tree maybe_fold_stmt_addition (location_t, tree, tree, tree);
-tree get_symbol_constant_value (tree);
-bool may_propagate_address_into_dereference (tree, tree);
-
-
 #endif  /* GCC_GIMPLE_H */
 #endif  /* GCC_GIMPLE_H */
index ed70d74..bd91e3b 100644 (file)
@@ -1,5 +1,5 @@
 /* Data flow functions for trees.
 /* Data flow functions for trees.
-   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
+   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
    Free Software Foundation, Inc.
    Contributed by Diego Novillo <dnovillo@redhat.com>
 
    Free Software Foundation, Inc.
    Contributed by Diego Novillo <dnovillo@redhat.com>
 
@@ -26,7 +26,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "hashtab.h"
 #include "pointer-set.h"
 #include "tree.h"
 #include "hashtab.h"
 #include "pointer-set.h"
 #include "tree.h"
+#include "rtl.h"
 #include "tm_p.h"
 #include "tm_p.h"
+#include "hard-reg-set.h"
 #include "basic-block.h"
 #include "output.h"
 #include "timevar.h"
 #include "basic-block.h"
 #include "output.h"
 #include "timevar.h"
@@ -36,7 +38,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "flags.h"
 #include "function.h"
 #include "diagnostic.h"
 #include "flags.h"
 #include "function.h"
 #include "diagnostic.h"
-#include "tree-pretty-print.h"
 #include "tree-dump.h"
 #include "gimple.h"
 #include "tree-flow.h"
 #include "tree-dump.h"
 #include "gimple.h"
 #include "tree-flow.h"
@@ -192,7 +193,11 @@ renumber_gimple_stmt_uids_in_blocks (basic_block *blocks, int n_blocks)
 tree
 make_rename_temp (tree type, const char *prefix)
 {
 tree
 make_rename_temp (tree type, const char *prefix)
 {
-  tree t = create_tmp_reg (type, prefix);
+  tree t = create_tmp_var (type, prefix);
+
+  if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
+      || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
+    DECL_GIMPLE_REG_P (t) = 1;
 
   if (gimple_referenced_vars (cfun))
     {
 
   if (gimple_referenced_vars (cfun))
     {
@@ -264,8 +269,6 @@ dump_variable (FILE *file, tree var)
   ann = var_ann (var);
 
   fprintf (file, ", UID D.%u", (unsigned) DECL_UID (var));
   ann = var_ann (var);
 
   fprintf (file, ", UID D.%u", (unsigned) DECL_UID (var));
-  if (DECL_PT_UID (var) != DECL_UID (var))
-    fprintf (file, ", PT-UID D.%u", (unsigned) DECL_PT_UID (var));
 
   fprintf (file, ", ");
   print_generic_expr (file, TREE_TYPE (var), dump_flags);
 
   fprintf (file, ", ");
   print_generic_expr (file, TREE_TYPE (var), dump_flags);
@@ -279,6 +282,9 @@ dump_variable (FILE *file, tree var)
   if (TREE_THIS_VOLATILE (var))
     fprintf (file, ", is volatile");
 
   if (TREE_THIS_VOLATILE (var))
     fprintf (file, ", is volatile");
 
+  if (is_call_clobbered (var))
+    fprintf (file, ", call clobbered");
+
   if (ann && ann->noalias_state == NO_ALIAS)
     fprintf (file, ", NO_ALIAS (does not alias other NO_ALIAS symbols)");
   else if (ann && ann->noalias_state == NO_ALIAS_GLOBAL)
   if (ann && ann->noalias_state == NO_ALIAS)
     fprintf (file, ", NO_ALIAS (does not alias other NO_ALIAS symbols)");
   else if (ann && ann->noalias_state == NO_ALIAS_GLOBAL)
index f7609ea..2430f03 100644 (file)
@@ -624,6 +624,15 @@ loop_containing_stmt (gimple stmt)
 }
 
 
 }
 
 
+/* Return true if VAR is clobbered by function calls.  */
+static inline bool
+is_call_clobbered (const_tree var)
+{
+  return (is_global_var (var)
+         || (may_be_aliased (var)
+             && pt_solution_includes (&cfun->gimple_df->escaped, var)));
+}
+
 /*  -----------------------------------------------------------------------  */
 
 /* The following set of routines are used to iterator over various type of
 /*  -----------------------------------------------------------------------  */
 
 /* The following set of routines are used to iterator over various type of
index 4c51f3b..922ce52 100644 (file)
@@ -26,6 +26,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "toplev.h"
 #include "tree.h"
 #include "tree-inline.h"
 #include "toplev.h"
 #include "tree.h"
 #include "tree-inline.h"
+#include "rtl.h"
 #include "expr.h"
 #include "flags.h"
 #include "params.h"
 #include "expr.h"
 #include "flags.h"
 #include "params.h"
@@ -40,9 +41,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-mudflap.h"
 #include "tree-flow.h"
 #include "function.h"
 #include "tree-mudflap.h"
 #include "tree-flow.h"
 #include "function.h"
+#include "ggc.h"
 #include "tree-flow.h"
 #include "diagnostic.h"
 #include "tree-flow.h"
 #include "diagnostic.h"
-#include "tree-pretty-print.h"
 #include "except.h"
 #include "debug.h"
 #include "pointer-set.h"
 #include "except.h"
 #include "debug.h"
 #include "pointer-set.h"
@@ -101,6 +102,10 @@ along with GCC; see the file COPYING3.  If not see
      calls?  */
 
 
      calls?  */
 
 
+/* Weights that estimate_num_insns uses for heuristics in inlining.  */
+
+eni_weights eni_inlining_weights;
+
 /* Weights that estimate_num_insns uses to estimate the size of the
    produced code.  */
 
 /* Weights that estimate_num_insns uses to estimate the size of the
    produced code.  */
 
@@ -206,21 +211,11 @@ remap_ssa_name (tree name, copy_body_data *id)
       && (TREE_CODE (SSA_NAME_VAR (name)) != RESULT_DECL
          || !id->transform_return_to_modify))
     {
       && (TREE_CODE (SSA_NAME_VAR (name)) != RESULT_DECL
          || !id->transform_return_to_modify))
     {
-      struct ptr_info_def *pi;
       new_tree = make_ssa_name (new_tree, NULL);
       insert_decl_map (id, name, new_tree);
       SSA_NAME_OCCURS_IN_ABNORMAL_PHI (new_tree)
        = SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name);
       TREE_TYPE (new_tree) = TREE_TYPE (SSA_NAME_VAR (new_tree));
       new_tree = make_ssa_name (new_tree, NULL);
       insert_decl_map (id, name, new_tree);
       SSA_NAME_OCCURS_IN_ABNORMAL_PHI (new_tree)
        = SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name);
       TREE_TYPE (new_tree) = TREE_TYPE (SSA_NAME_VAR (new_tree));
-      /* At least IPA points-to info can be directly transferred.  */
-      if (id->src_cfun->gimple_df
-         && id->src_cfun->gimple_df->ipa_pta
-         && (pi = SSA_NAME_PTR_INFO (name))
-         && !pi->pt.anything)
-       {
-         struct ptr_info_def *new_pi = get_ptr_info (new_tree);
-         new_pi->pt = pi->pt;
-       }
       if (gimple_nop_p (SSA_NAME_DEF_STMT (name)))
        {
          /* By inlining function having uninitialized variable, we might
       if (gimple_nop_p (SSA_NAME_DEF_STMT (name)))
        {
          /* By inlining function having uninitialized variable, we might
@@ -665,30 +660,16 @@ copy_bind_expr (tree *tp, int *walk_subtrees, copy_body_data *id)
     }
 
   if (BIND_EXPR_VARS (*tp))
     }
 
   if (BIND_EXPR_VARS (*tp))
-    {
-      tree t;
-
-      /* This will remap a lot of the same decls again, but this should be
-        harmless.  */
-      BIND_EXPR_VARS (*tp) = remap_decls (BIND_EXPR_VARS (*tp), NULL, id);
-      /* Also copy value-expressions.  */
-      for (t = BIND_EXPR_VARS (*tp); t; t = TREE_CHAIN (t))
-       if (TREE_CODE (t) == VAR_DECL
-           && DECL_HAS_VALUE_EXPR_P (t))
-         {
-           tree tem = DECL_VALUE_EXPR (t);
-           walk_tree (&tem, copy_tree_body_r, id, NULL);
-           SET_DECL_VALUE_EXPR (t, tem);
-         }
-    }
+    /* This will remap a lot of the same decls again, but this should be
+       harmless.  */
+    BIND_EXPR_VARS (*tp) = remap_decls (BIND_EXPR_VARS (*tp), NULL, id);
 }
 
 
 /* Create a new gimple_seq by remapping all the statements in BODY
    using the inlining information in ID.  */
 
 }
 
 
 /* Create a new gimple_seq by remapping all the statements in BODY
    using the inlining information in ID.  */
 
-static gimple_seq
+gimple_seq
 remap_gimple_seq (gimple_seq body, copy_body_data *id)
 {
   gimple_stmt_iterator si;
 remap_gimple_seq (gimple_seq body, copy_body_data *id)
 {
   gimple_stmt_iterator si;
@@ -1411,11 +1392,12 @@ remap_gimple_stmt (gimple stmt, copy_body_data *id)
                    break;
                  }
 
                    break;
                  }
 
-             /* Reset alias info if we didn't apply measures to
-                keep it valid over inlining by setting DECL_PT_UID.  */
-             if (!id->src_cfun->gimple_df
-                 || !id->src_cfun->gimple_df->ipa_pta)
-               gimple_call_reset_alias_info (copy);
+             /* 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;
 
            }
            break;
 
@@ -1698,8 +1680,9 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
              /* Constant propagation on argument done during inlining
                 may create new direct call.  Produce an edge for it.  */
              if ((!edge
              /* Constant propagation on argument done during inlining
                 may create new direct call.  Produce an edge for it.  */
              if ((!edge
-                  || (edge->indirect_inlining_edge
+                  || (edge->indirect_call
                       && id->transform_call_graph_edges == CB_CGE_MOVE_CLONES))
                       && id->transform_call_graph_edges == CB_CGE_MOVE_CLONES))
+                 && is_gimple_call (stmt)
                  && (fn = gimple_call_fndecl (stmt)) != NULL)
                {
                  struct cgraph_node *dest = cgraph_node (fn);
                  && (fn = gimple_call_fndecl (stmt)) != NULL)
                {
                  struct cgraph_node *dest = cgraph_node (fn);
@@ -1711,7 +1694,6 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
                     other cases we hit a bug (incorrect node sharing is the
                     most common reason for missing edges).  */
                  gcc_assert (dest->needed || !dest->analyzed
                     other cases we hit a bug (incorrect node sharing is the
                     most common reason for missing edges).  */
                  gcc_assert (dest->needed || !dest->analyzed
-                             || dest->address_taken
                              || !id->src_node->analyzed);
                  if (id->transform_call_graph_edges == CB_CGE_MOVE_CLONES)
                    cgraph_create_edge_including_clones
                              || !id->src_node->analyzed);
                  if (id->transform_call_graph_edges == CB_CGE_MOVE_CLONES)
                    cgraph_create_edge_including_clones
@@ -2024,6 +2006,7 @@ initialize_cfun (tree new_fndecl, tree callee_fndecl, gcov_type count)
   cfun->last_verified = src_cfun->last_verified;
   cfun->va_list_gpr_size = src_cfun->va_list_gpr_size;
   cfun->va_list_fpr_size = src_cfun->va_list_fpr_size;
   cfun->last_verified = src_cfun->last_verified;
   cfun->va_list_gpr_size = src_cfun->va_list_gpr_size;
   cfun->va_list_fpr_size = src_cfun->va_list_fpr_size;
+  cfun->function_frequency = src_cfun->function_frequency;
   cfun->has_nonlocal_label = src_cfun->has_nonlocal_label;
   cfun->stdarg = src_cfun->stdarg;
   cfun->dont_save_pending_sizes_p = src_cfun->dont_save_pending_sizes_p;
   cfun->has_nonlocal_label = src_cfun->has_nonlocal_label;
   cfun->stdarg = src_cfun->stdarg;
   cfun->dont_save_pending_sizes_p = src_cfun->dont_save_pending_sizes_p;
@@ -3278,93 +3261,22 @@ estimate_num_insns (gimple stmt, eni_weights *weights)
        if (decl && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
          switch (DECL_FUNCTION_CODE (decl))
            {
        if (decl && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
          switch (DECL_FUNCTION_CODE (decl))
            {
-           /* Builtins that expand to constants.  */
            case BUILT_IN_CONSTANT_P:
            case BUILT_IN_CONSTANT_P:
+             return 0;
            case BUILT_IN_EXPECT:
            case BUILT_IN_EXPECT:
-           case BUILT_IN_OBJECT_SIZE:
-           case BUILT_IN_UNREACHABLE:
-           /* Simple register moves or loads from stack.  */
-           case BUILT_IN_RETURN_ADDRESS:
-           case BUILT_IN_EXTRACT_RETURN_ADDR:
-           case BUILT_IN_FROB_RETURN_ADDR:
-           case BUILT_IN_RETURN:
-           case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
-           case BUILT_IN_FRAME_ADDRESS:
-           case BUILT_IN_VA_END:
-           case BUILT_IN_STACK_SAVE:
-           case BUILT_IN_STACK_RESTORE:
-           /* Exception state returns or moves registers around.  */
-           case BUILT_IN_EH_FILTER:
-           case BUILT_IN_EH_POINTER:
-           case BUILT_IN_EH_COPY_VALUES:
              return 0;
 
              return 0;
 
-           /* builtins that are not expensive (that is they are most probably
-              expanded inline into resonably simple code).  */
-           case BUILT_IN_ABS:
-           case BUILT_IN_ALLOCA:
-           case BUILT_IN_BSWAP32:
-           case BUILT_IN_BSWAP64:
-           case BUILT_IN_CLZ:
-           case BUILT_IN_CLZIMAX:
-           case BUILT_IN_CLZL:
-           case BUILT_IN_CLZLL:
-           case BUILT_IN_CTZ:
-           case BUILT_IN_CTZIMAX:
-           case BUILT_IN_CTZL:
-           case BUILT_IN_CTZLL:
-           case BUILT_IN_FFS:
-           case BUILT_IN_FFSIMAX:
-           case BUILT_IN_FFSL:
-           case BUILT_IN_FFSLL:
-           case BUILT_IN_IMAXABS:
-           case BUILT_IN_FINITE:
-           case BUILT_IN_FINITEF:
-           case BUILT_IN_FINITEL:
-           case BUILT_IN_FINITED32:
-           case BUILT_IN_FINITED64:
-           case BUILT_IN_FINITED128:
-           case BUILT_IN_FPCLASSIFY:
-           case BUILT_IN_ISFINITE:
-           case BUILT_IN_ISINF_SIGN:
-           case BUILT_IN_ISINF:
-           case BUILT_IN_ISINFF:
-           case BUILT_IN_ISINFL:
-           case BUILT_IN_ISINFD32:
-           case BUILT_IN_ISINFD64:
-           case BUILT_IN_ISINFD128:
-           case BUILT_IN_ISNAN:
-           case BUILT_IN_ISNANF:
-           case BUILT_IN_ISNANL:
-           case BUILT_IN_ISNAND32:
-           case BUILT_IN_ISNAND64:
-           case BUILT_IN_ISNAND128:
-           case BUILT_IN_ISNORMAL:
-           case BUILT_IN_ISGREATER:
-           case BUILT_IN_ISGREATEREQUAL:
-           case BUILT_IN_ISLESS:
-           case BUILT_IN_ISLESSEQUAL:
-           case BUILT_IN_ISLESSGREATER:
-           case BUILT_IN_ISUNORDERED:
-           case BUILT_IN_VA_ARG_PACK:
-           case BUILT_IN_VA_ARG_PACK_LEN:
-           case BUILT_IN_VA_COPY:
-           case BUILT_IN_TRAP:
-           case BUILT_IN_SAVEREGS:
-           case BUILT_IN_POPCOUNTL:
-           case BUILT_IN_POPCOUNTLL:
-           case BUILT_IN_POPCOUNTIMAX:
-           case BUILT_IN_POPCOUNT:
-           case BUILT_IN_PARITYL:
-           case BUILT_IN_PARITYLL:
-           case BUILT_IN_PARITYIMAX:
-           case BUILT_IN_PARITY:
-           case BUILT_IN_LABS:
-           case BUILT_IN_LLABS:
+           /* Prefetch instruction is not expensive.  */
            case BUILT_IN_PREFETCH:
              cost = weights->target_builtin_call_cost;
              break;
 
            case BUILT_IN_PREFETCH:
              cost = weights->target_builtin_call_cost;
              break;
 
+           /* Exception state returns or moves registers around.  */
+           case BUILT_IN_EH_FILTER:
+           case BUILT_IN_EH_POINTER:
+           case BUILT_IN_EH_COPY_VALUES:
+             return 0;
+
            default:
              break;
            }
            default:
              break;
            }
@@ -3553,7 +3465,7 @@ get_indirect_callee_fndecl (struct cgraph_node *node, gimple stmt)
   struct cgraph_edge *cs;
 
   cs = cgraph_edge (node, stmt);
   struct cgraph_edge *cs;
 
   cs = cgraph_edge (node, stmt);
-  if (cs && !cs->indirect_unknown_callee)
+  if (cs)
     return cs->callee->decl;
 
   return NULL_TREE;
     return cs->callee->decl;
 
   return NULL_TREE;
@@ -3636,7 +3548,7 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id)
       /* If this call was originally indirect, we do not want to emit any
         inlining related warnings or sorry messages because there are no
         guarantees regarding those.  */
       /* If this call was originally indirect, we do not want to emit any
         inlining related warnings or sorry messages because there are no
         guarantees regarding those.  */
-      if (cg_edge->indirect_inlining_edge)
+      if (cg_edge->indirect_call)
        goto egress;
 
       if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn))
        goto egress;
 
       if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn))
@@ -4604,8 +4516,6 @@ copy_decl_to_var (tree decl, copy_body_data *id)
 
   copy = build_decl (DECL_SOURCE_LOCATION (id->dst_fn),
                     VAR_DECL, DECL_NAME (decl), type);
 
   copy = build_decl (DECL_SOURCE_LOCATION (id->dst_fn),
                     VAR_DECL, DECL_NAME (decl), type);
-  if (DECL_PT_UID_SET_P (decl))
-    SET_DECL_PT_UID (copy, DECL_PT_UID (decl));
   TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (decl);
   TREE_READONLY (copy) = TREE_READONLY (decl);
   TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (decl);
   TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (decl);
   TREE_READONLY (copy) = TREE_READONLY (decl);
   TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (decl);
@@ -4631,8 +4541,6 @@ copy_result_decl_to_var (tree decl, copy_body_data *id)
 
   copy = build_decl (DECL_SOURCE_LOCATION (id->dst_fn),
                     VAR_DECL, DECL_NAME (decl), type);
 
   copy = build_decl (DECL_SOURCE_LOCATION (id->dst_fn),
                     VAR_DECL, DECL_NAME (decl), type);
-  if (DECL_PT_UID_SET_P (decl))
-    SET_DECL_PT_UID (copy, DECL_PT_UID (decl));
   TREE_READONLY (copy) = TREE_READONLY (decl);
   TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (decl);
   if (!DECL_BY_REFERENCE (decl))
   TREE_READONLY (copy) = TREE_READONLY (decl);
   TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (decl);
   if (!DECL_BY_REFERENCE (decl))
@@ -4925,8 +4833,6 @@ tree_function_versioning (tree old_decl, tree new_decl,
     (DECL_STRUCT_FUNCTION (old_decl));
   initialize_cfun (new_decl, old_decl,
                   old_entry_block->count);
     (DECL_STRUCT_FUNCTION (old_decl));
   initialize_cfun (new_decl, old_decl,
                   old_entry_block->count);
-  DECL_STRUCT_FUNCTION (new_decl)->gimple_df->ipa_pta
-    = id.src_cfun->gimple_df->ipa_pta;
   push_cfun (DECL_STRUCT_FUNCTION (new_decl));
 
   /* Copy the function's static chain.  */
   push_cfun (DECL_STRUCT_FUNCTION (new_decl));
 
   /* Copy the function's static chain.  */
@@ -4945,15 +4851,6 @@ tree_function_versioning (tree old_decl, tree new_decl,
        if (replace_info->replace_p)
          {
            tree op = replace_info->new_tree;
        if (replace_info->replace_p)
          {
            tree op = replace_info->new_tree;
-           if (!replace_info->old_tree)
-             {
-               int i = replace_info->parm_num;
-               tree parm;
-               for (parm = DECL_ARGUMENTS (old_decl); i; parm = TREE_CHAIN (parm))
-                 i --;
-               replace_info->old_tree = parm;
-             }
-               
 
            STRIP_NOPS (op);
 
 
            STRIP_NOPS (op);
 
@@ -5047,8 +4944,6 @@ tree_function_versioning (tree old_decl, tree new_decl,
   pointer_set_destroy (id.statements_to_fold);
   fold_cond_expr_cond ();
   delete_unreachable_blocks_update_callgraph (&id);
   pointer_set_destroy (id.statements_to_fold);
   fold_cond_expr_cond ();
   delete_unreachable_blocks_update_callgraph (&id);
-  if (id.dst_node->analyzed)
-    cgraph_rebuild_references ();
   update_ssa (TODO_update_ssa);
   free_dominance_info (CDI_DOMINATORS);
   free_dominance_info (CDI_POST_DOMINATORS);
   update_ssa (TODO_update_ssa);
   free_dominance_info (CDI_DOMINATORS);
   free_dominance_info (CDI_POST_DOMINATORS);
@@ -5175,7 +5070,7 @@ tree_can_inline_p (struct cgraph_edge *e)
        return false;
     }
 #endif
        return false;
     }
 #endif
-  tree caller, callee, lhs;
+  tree caller, callee;
 
   caller = e->caller->decl;
   callee = e->callee->decl;
 
   caller = e->caller->decl;
   callee = e->callee->decl;
@@ -5201,16 +5096,8 @@ tree_can_inline_p (struct cgraph_edge *e)
       return false;
     }
 
       return false;
     }
 
-  /* Do not inline calls where we cannot triviall work around mismatches
-     in argument or return types.  */
   if (e->call_stmt
   if (e->call_stmt
-      && ((DECL_RESULT (callee)
-          && !DECL_BY_REFERENCE (DECL_RESULT (callee))
-          && (lhs = gimple_call_lhs (e->call_stmt)) != NULL_TREE
-          && !useless_type_conversion_p (TREE_TYPE (DECL_RESULT (callee)),
-                                         TREE_TYPE (lhs))
-          && !fold_convertible_p (TREE_TYPE (DECL_RESULT (callee)), lhs))
-         || !gimple_check_call_args (e->call_stmt)))
+      && !gimple_check_call_args (e->call_stmt))
     {
       e->inline_failed = CIF_MISMATCHED_ARGUMENTS;
       gimple_call_set_cannot_inline (e->call_stmt, true);
     {
       e->inline_failed = CIF_MISMATCHED_ARGUMENTS;
       gimple_call_set_cannot_inline (e->call_stmt, true);
index 06b1351..b85c5a7 100644 (file)
@@ -1,6 +1,5 @@
 /* Language independent return value optimizations
 /* Language independent return value optimizations
-   Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010
-   Free Software Foundation, Inc.
+   Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 
 This file is part of GCC.
 
@@ -23,18 +22,16 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
+#include "rtl.h"
 #include "function.h"
 #include "basic-block.h"
 #include "function.h"
 #include "basic-block.h"
+#include "expr.h"
 #include "diagnostic.h"
 #include "diagnostic.h"
-#include "tree-pretty-print.h"
 #include "tree-flow.h"
 #include "timevar.h"
 #include "tree-dump.h"
 #include "tree-pass.h"
 #include "langhooks.h"
 #include "tree-flow.h"
 #include "timevar.h"
 #include "tree-dump.h"
 #include "tree-pass.h"
 #include "langhooks.h"
-#include "flags.h"     /* For "optimize" in gate_pass_return_slot.
-                          FIXME: That should be up to the pass manager,
-                          but pass_nrv is not in pass_all_optimizations.  */
 
 /* This file implements return value optimizations for functions which
    return aggregate types.
 
 /* This file implements return value optimizations for functions which
    return aggregate types.
@@ -294,21 +291,23 @@ struct gimple_opt_pass pass_nrv =
    optimization, where DEST is expected to be the LHS of a modify
    expression where the RHS is a function returning an aggregate.
 
    optimization, where DEST is expected to be the LHS of a modify
    expression where the RHS is a function returning an aggregate.
 
-   DEST is available if it is not clobbered by the call.  */
+   We search for a base VAR_DECL and look to see if it is call clobbered.
+   Note that we could do better, for example, by
+   attempting to doing points-to analysis on INDIRECT_REFs.  */
 
 static bool
 
 static bool
-dest_safe_for_nrv_p (gimple call)
+dest_safe_for_nrv_p (tree dest)
 {
 {
-  tree dest = gimple_call_lhs (call);
+  while (handled_component_p (dest))
+    dest = TREE_OPERAND (dest, 0);
 
 
-  dest = get_base_address (dest);
-  if (! dest)
+  if (! SSA_VAR_P (dest))
     return false;
 
   if (TREE_CODE (dest) == SSA_NAME)
     return false;
 
   if (TREE_CODE (dest) == SSA_NAME)
-    return true;
+    dest = SSA_NAME_VAR (dest);
 
 
-  if (call_may_clobber_ref_p (call, dest))
+  if (is_call_clobbered (dest))
     return false;
 
   return true;
     return false;
 
   return true;
@@ -347,8 +346,8 @@ execute_return_slot_opt (void)
             )
            {
              /* Check if the location being assigned to is
             )
            {
              /* Check if the location being assigned to is
-                clobbered by the call.  */
-             slot_opt_p = dest_safe_for_nrv_p (stmt);
+                call-clobbered.  */
+             slot_opt_p = dest_safe_for_nrv_p (gimple_call_lhs (stmt));
              gimple_call_set_return_slot_opt (stmt, slot_opt_p);
            }
        }
              gimple_call_set_return_slot_opt (stmt, slot_opt_p);
            }
        }
index a5a9634..e14b97a 100644 (file)
 #include "obstack.h"
 #include "bitmap.h"
 #include "flags.h"
 #include "obstack.h"
 #include "bitmap.h"
 #include "flags.h"
+#include "rtl.h"
+#include "tm_p.h"
+#include "hard-reg-set.h"
 #include "basic-block.h"
 #include "output.h"
 #include "tree.h"
 #include "tree-flow.h"
 #include "tree-inline.h"
 #include "basic-block.h"
 #include "output.h"
 #include "tree.h"
 #include "tree-flow.h"
 #include "tree-inline.h"
+#include "varray.h"
 #include "diagnostic.h"
 #include "toplev.h"
 #include "gimple.h"
 #include "diagnostic.h"
 #include "toplev.h"
 #include "gimple.h"
   TODO: We could handle unions, but to be honest, it's probably not
   worth the pain or slowdown.  */
 
   TODO: We could handle unions, but to be honest, it's probably not
   worth the pain or slowdown.  */
 
-/* IPA-PTA optimizations possible.
-
-   When the indirect function called is ANYTHING we can add disambiguation
-   based on the function signatures (or simply the parameter count which
-   is the varinfo size).  We also do not need to consider functions that
-   do not have their address taken.
-
-   The is_global_var bit which marks escape points is overly conservative
-   in IPA mode.  Split it to is_escape_point and is_global_var - only
-   externally visible globals are escape points in IPA mode.  This is
-   also needed to fix the pt_solution_includes_global predicate
-   (and thus ptr_deref_may_alias_global_p).
-
-   The way we introduce DECL_PT_UID to avoid fixing up all points-to
-   sets in the translation unit when we copy a DECL during inlining
-   pessimizes precision.  The advantage is that the DECL_PT_UID keeps
-   compile-time and memory usage overhead low - the points-to sets
-   do not grow or get unshared as they would during a fixup phase.
-   An alternative solution is to delay IPA PTA until after all
-   inlining transformations have been applied.
-
-   The way we propagate clobber/use information isn't optimized.
-   It should use a new complex constraint that properly filters
-   out local variables of the callee (though that would make
-   the sets invalid after inlining).  OTOH we might as well
-   admit defeat to WHOPR and simply do all the clobber/use analysis
-   and propagation after PTA finished but before we threw away
-   points-to information for memory variables.  WHOPR and PTA
-   do not play along well anyway - the whole constraint solving
-   would need to be done in WPA phase and it will be very interesting
-   to apply the results to local SSA names during LTRANS phase.
-
-   We probably should compute a per-function unit-ESCAPE solution
-   propagating it simply like the clobber / uses solutions.  The
-   solution can go alongside the non-IPA espaced solution and be
-   used to query which vars escape the unit through a function.
-
-   We never put function decls in points-to sets so we do not
-   keep the set of called functions for indirect calls.
-
-   And probably more.  */
-
 static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map)))
 htab_t heapvar_for_stmt;
 
 static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map)))
 htab_t heapvar_for_stmt;
 
@@ -271,15 +233,9 @@ struct variable_info
   /* True if this field may contain pointers.  */
   unsigned int may_have_pointers : 1;
 
   /* True if this field may contain pointers.  */
   unsigned int may_have_pointers : 1;
 
-  /* True if this field has only restrict qualified pointers.  */
-  unsigned int only_restrict_pointers : 1;
-
   /* True if this represents a global variable.  */
   unsigned int is_global_var : 1;
 
   /* True if this represents a global variable.  */
   unsigned int is_global_var : 1;
 
-  /* True if this represents a IPA function info.  */
-  unsigned int is_fn_info : 1;
-
   /* A link to the variable for the next field in this structure.  */
   struct variable_info *next;
 
   /* A link to the variable for the next field in this structure.  */
   struct variable_info *next;
 
@@ -332,8 +288,8 @@ get_varinfo (unsigned int n)
 
 /* Static IDs for the special variables.  */
 enum { nothing_id = 0, anything_id = 1, readonly_id = 2,
 
 /* Static IDs for the special variables.  */
 enum { nothing_id = 0, anything_id = 1, readonly_id = 2,
-       escaped_id = 3, nonlocal_id = 4,
-       storedanything_id = 5, integer_id = 6 };
+       escaped_id = 3, nonlocal_id = 4, callused_id = 5,
+       storedanything_id = 6, integer_id = 7 };
 
 struct GTY(()) heapvar_map {
   struct tree_map map;
 
 struct GTY(()) heapvar_map {
   struct tree_map map;
@@ -411,102 +367,18 @@ new_var_info (tree t, const char *name)
   ret->is_heap_var = false;
   ret->is_restrict_var = false;
   ret->may_have_pointers = true;
   ret->is_heap_var = false;
   ret->is_restrict_var = false;
   ret->may_have_pointers = true;
-  ret->only_restrict_pointers = false;
   ret->is_global_var = (t == NULL_TREE);
   ret->is_global_var = (t == NULL_TREE);
-  ret->is_fn_info = false;
   if (t && DECL_P (t))
     ret->is_global_var = is_global_var (t);
   ret->solution = BITMAP_ALLOC (&pta_obstack);
   ret->oldsolution = BITMAP_ALLOC (&oldpta_obstack);
   ret->next = NULL;
 
   if (t && DECL_P (t))
     ret->is_global_var = is_global_var (t);
   ret->solution = BITMAP_ALLOC (&pta_obstack);
   ret->oldsolution = BITMAP_ALLOC (&oldpta_obstack);
   ret->next = NULL;
 
-  stats.total_vars++;
-
   VEC_safe_push (varinfo_t, heap, varmap, ret);
 
   return ret;
 }
 
   VEC_safe_push (varinfo_t, heap, varmap, ret);
 
   return ret;
 }
 
-
-/* A map mapping call statements to per-stmt variables for uses
-   and clobbers specific to the call.  */
-struct pointer_map_t *call_stmt_vars;
-
-/* Lookup or create the variable for the call statement CALL.  */
-
-static varinfo_t
-get_call_vi (gimple call)
-{
-  void **slot_p;
-  varinfo_t vi, vi2;
-
-  slot_p = pointer_map_insert (call_stmt_vars, call);
-  if (*slot_p)
-    return (varinfo_t) *slot_p;
-
-  vi = new_var_info (NULL_TREE, "CALLUSED");
-  vi->offset = 0;
-  vi->size = 1;
-  vi->fullsize = 2;
-  vi->is_full_var = true;
-
-  vi->next = vi2 = new_var_info (NULL_TREE, "CALLCLOBBERED");
-  vi2->offset = 1;
-  vi2->size = 1;
-  vi2->fullsize = 2;
-  vi2->is_full_var = true;
-
-  *slot_p = (void *) vi;
-  return vi;
-}
-
-/* Lookup the variable for the call statement CALL representing
-   the uses.  Returns NULL if there is nothing special about this call.  */
-
-static varinfo_t
-lookup_call_use_vi (gimple call)
-{
-  void **slot_p;
-
-  slot_p = pointer_map_contains (call_stmt_vars, call);
-  if (slot_p)
-    return (varinfo_t) *slot_p;
-
-  return NULL;
-}
-
-/* Lookup the variable for the call statement CALL representing
-   the clobbers.  Returns NULL if there is nothing special about this call.  */
-
-static varinfo_t
-lookup_call_clobber_vi (gimple call)
-{
-  varinfo_t uses = lookup_call_use_vi (call);
-  if (!uses)
-    return NULL;
-
-  return uses->next;
-}
-
-/* Lookup or create the variable for the call statement CALL representing
-   the uses.  */
-
-static varinfo_t
-get_call_use_vi (gimple call)
-{
-  return get_call_vi (call);
-}
-
-/* Lookup or create the variable for the call statement CALL representing
-   the clobbers.  */
-
-static varinfo_t ATTRIBUTE_UNUSED
-get_call_clobber_vi (gimple call)
-{
-  return get_call_vi (call)->next;
-}
-
-
 typedef enum {SCALAR, DEREF, ADDRESSOF} constraint_expr_type;
 
 /* An expression that appears in a constraint.  */
 typedef enum {SCALAR, DEREF, ADDRESSOF} constraint_expr_type;
 
 /* An expression that appears in a constraint.  */
@@ -725,11 +597,11 @@ debug_constraint (constraint_t c)
 /* Print out all constraints to FILE */
 
 static void
 /* Print out all constraints to FILE */
 
 static void
-dump_constraints (FILE *file, int from)
+dump_constraints (FILE *file)
 {
   int i;
   constraint_t c;
 {
   int i;
   constraint_t c;
-  for (i = from; VEC_iterate (constraint_t, constraints, i, c); i++)
+  for (i = 0; VEC_iterate (constraint_t, constraints, i, c); i++)
     dump_constraint (file, c);
 }
 
     dump_constraint (file, c);
 }
 
@@ -738,7 +610,7 @@ dump_constraints (FILE *file, int from)
 void
 debug_constraints (void)
 {
 void
 debug_constraints (void)
 {
-  dump_constraints (stderr, 0);
+  dump_constraints (stderr);
 }
 
 /* Print out to FILE the edge in the constraint graph that is created by
 }
 
 /* Print out to FILE the edge in the constraint graph that is created by
@@ -789,7 +661,7 @@ dump_constraint_graph (FILE *file)
   /* Print the constraints used to produce the constraint graph. The
      constraints will be printed as comments in the dot file:  */
   fprintf (file, "\n\n/* Constraints used in the constraint graph:\n");
   /* Print the constraints used to produce the constraint graph. The
      constraints will be printed as comments in the dot file:  */
   fprintf (file, "\n\n/* Constraints used in the constraint graph:\n");
-  dump_constraints (file, 0);
+  dump_constraints (file);
   fprintf (file, "*/\n");
 
   /* Prints the header of the dot file:  */
   fprintf (file, "*/\n");
 
   /* Prints the header of the dot file:  */
@@ -1708,8 +1580,7 @@ do_sd_constraint (constraint_graph_t graph, constraint_t c,
             the set.  Use ESCAPED as representative instead.  */
          else if (v->id == escaped_id)
            flag |= bitmap_set_bit (sol, escaped_id);
             the set.  Use ESCAPED as representative instead.  */
          else if (v->id == escaped_id)
            flag |= bitmap_set_bit (sol, escaped_id);
-         else if (v->may_have_pointers
-                  && add_graph_edge (graph, lhs, t))
+         else if (add_graph_edge (graph, lhs, t))
            flag |= bitmap_ior_into (sol, get_varinfo (t)->solution);
 
          /* If the variable is not exactly at the requested offset
            flag |= bitmap_ior_into (sol, get_varinfo (t)->solution);
 
          /* If the variable is not exactly at the requested offset
@@ -1748,7 +1619,6 @@ do_ds_constraint (constraint_t c, bitmap delta)
   unsigned int j;
   bitmap_iterator bi;
   HOST_WIDE_INT loff = c->lhs.offset;
   unsigned int j;
   bitmap_iterator bi;
   HOST_WIDE_INT loff = c->lhs.offset;
-  bool escaped_p = false;
 
   /* Our IL does not allow this.  */
   gcc_assert (c->rhs.offset == 0);
 
   /* Our IL does not allow this.  */
   gcc_assert (c->rhs.offset == 0);
@@ -1795,6 +1665,22 @@ do_ds_constraint (constraint_t c, bitmap delta)
       unsigned int t;
       HOST_WIDE_INT fieldoffset = v->offset + loff;
 
       unsigned int t;
       HOST_WIDE_INT fieldoffset = v->offset + loff;
 
+      /* If v is a global variable then this is an escape point.  */
+      if (v->is_global_var)
+       {
+         t = find (escaped_id);
+         if (add_graph_edge (graph, t, rhs)
+             && bitmap_ior_into (get_varinfo (t)->solution, sol)
+             && !TEST_BIT (changed, t))
+           {
+             SET_BIT (changed, t);
+             changed_count++;
+           }
+       }
+
+      if (v->is_special_var)
+       continue;
+
       if (v->is_full_var)
        fieldoffset = v->offset;
       else if (loff != 0)
       if (v->is_full_var)
        fieldoffset = v->offset;
       else if (loff != 0)
@@ -1807,25 +1693,6 @@ do_ds_constraint (constraint_t c, bitmap delta)
        {
          if (v->may_have_pointers)
            {
        {
          if (v->may_have_pointers)
            {
-             /* If v is a global variable then this is an escape point.  */
-             if (v->is_global_var
-                 && !escaped_p)
-               {
-                 t = find (escaped_id);
-                 if (add_graph_edge (graph, t, rhs)
-                     && bitmap_ior_into (get_varinfo (t)->solution, sol)
-                     && !TEST_BIT (changed, t))
-                   {
-                     SET_BIT (changed, t);
-                     changed_count++;
-                   }
-                 /* Enough to let rhs escape once.  */
-                 escaped_p = true;
-               }
-
-             if (v->is_special_var)
-               break;
-
              t = find (v->id);
              if (add_graph_edge (graph, t, rhs)
                  && bitmap_ior_into (get_varinfo (t)->solution, sol)
              t = find (v->id);
              if (add_graph_edge (graph, t, rhs)
                  && bitmap_ior_into (get_varinfo (t)->solution, sol)
@@ -2756,14 +2623,10 @@ lookup_vi_for_tree (tree t)
 static const char *
 alias_get_name (tree decl)
 {
 static const char *
 alias_get_name (tree decl)
 {
-  const char *res;
+  const char *res = get_name (decl);
   char *temp;
   int num_printed = 0;
 
   char *temp;
   int num_printed = 0;
 
-  if (DECL_ASSEMBLER_NAME_SET_P (decl))
-    res = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
-  else
-    res= get_name (decl);
   if (res != NULL)
     return res;
 
   if (res != NULL)
     return res;
 
@@ -2896,16 +2759,6 @@ process_constraint (constraint_t t)
   /* ADDRESSOF on the lhs is invalid.  */
   gcc_assert (lhs.type != ADDRESSOF);
 
   /* ADDRESSOF on the lhs is invalid.  */
   gcc_assert (lhs.type != ADDRESSOF);
 
-  /* We shouldn't add constraints from things that cannot have pointers.
-     It's not completely trivial to avoid in the callers, so do it here.  */
-  if (rhs.type != ADDRESSOF
-      && !get_varinfo (rhs.var)->may_have_pointers)
-    return;
-
-  /* Likewise adding to the solution of a non-pointer var isn't useful.  */
-  if (!get_varinfo (lhs.var)->may_have_pointers)
-    return;
-
   /* This can happen in our IR with things like n->a = *p */
   if (rhs.type == DEREF && lhs.type == DEREF && rhs.var != anything_id)
     {
   /* This can happen in our IR with things like n->a = *p */
   if (rhs.type == DEREF && lhs.type == DEREF && rhs.var != anything_id)
     {
@@ -2941,12 +2794,6 @@ type_could_have_pointers (tree type)
   if (TREE_CODE (type) == ARRAY_TYPE)
     return type_could_have_pointers (TREE_TYPE (type));
 
   if (TREE_CODE (type) == ARRAY_TYPE)
     return type_could_have_pointers (TREE_TYPE (type));
 
-  /* A function or method can consume pointers.
-     ???  We could be more precise here.  */
-  if (TREE_CODE (type) == FUNCTION_TYPE
-      || TREE_CODE (type) == METHOD_TYPE)
-    return true;
-
   return AGGREGATE_TYPE_P (type);
 }
 
   return AGGREGATE_TYPE_P (type);
 }
 
@@ -2956,11 +2803,7 @@ type_could_have_pointers (tree type)
 static bool
 could_have_pointers (tree t)
 {
 static bool
 could_have_pointers (tree t)
 {
-  return (((TREE_CODE (t) == VAR_DECL
-           || TREE_CODE (t) == PARM_DECL
-           || TREE_CODE (t) == RESULT_DECL)
-          && (TREE_PUBLIC (t) || DECL_EXTERNAL (t) || TREE_ADDRESSABLE (t)))
-         || type_could_have_pointers (TREE_TYPE (t)));
+  return type_could_have_pointers (TREE_TYPE (t));
 }
 
 /* Return the position, in bits, of FIELD_DECL from the beginning of its
 }
 
 /* Return the position, in bits, of FIELD_DECL from the beginning of its
@@ -3291,18 +3134,14 @@ get_constraint_for_1 (tree t, VEC (ce_s, heap) **results, bool address_p)
      in that case *NULL does not fail, so it _should_ alias *anything.
      It is not worth adding a new option or renaming the existing one,
      since this case is relatively obscure.  */
      in that case *NULL does not fail, so it _should_ alias *anything.
      It is not worth adding a new option or renaming the existing one,
      since this case is relatively obscure.  */
-  if ((TREE_CODE (t) == INTEGER_CST
-       && integer_zerop (t))
-      /* The only valid CONSTRUCTORs in gimple with pointer typed
-        elements are zero-initializer.  But in IPA mode we also
-        process global initializers, so verify at least.  */
-      || (TREE_CODE (t) == CONSTRUCTOR
-         && CONSTRUCTOR_NELTS (t) == 0))
-    {
-      if (flag_delete_null_pointer_checks)
-       temp.var = nothing_id;
-      else
-       temp.var = anything_id;
+  if (flag_delete_null_pointer_checks
+      && ((TREE_CODE (t) == INTEGER_CST
+          && integer_zerop (t))
+         /* The only valid CONSTRUCTORs in gimple with pointer typed
+            elements are zero-initializer.  */
+         || TREE_CODE (t) == CONSTRUCTOR))
+    {
+      temp.var = nothing_id;
       temp.type = ADDRESSOF;
       temp.offset = 0;
       VEC_safe_push (ce_s, heap, *results, &temp);
       temp.type = ADDRESSOF;
       temp.offset = 0;
       VEC_safe_push (ce_s, heap, *results, &temp);
@@ -3364,26 +3203,6 @@ get_constraint_for_1 (tree t, VEC (ce_s, heap) **results, bool address_p)
              get_constraint_for_ssa_var (t, results, address_p);
              return;
            }
              get_constraint_for_ssa_var (t, results, address_p);
              return;
            }
-         case CONSTRUCTOR:
-           {
-             unsigned int i;
-             tree val;
-             VEC (ce_s, heap) *tmp = NULL;
-             FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (t), i, val)
-               {
-                 struct constraint_expr *rhsp;
-                 unsigned j;
-                 get_constraint_for_1 (val, &tmp, address_p);
-                 for (j = 0; VEC_iterate (ce_s, tmp, j, rhsp); ++j)
-                   VEC_safe_push (ce_s, heap, *results, rhsp);
-                 VEC_truncate (ce_s, tmp, 0);
-               }
-             VEC_free (ce_s, heap, tmp);
-             /* We do not know whether the constructor was complete,
-                so technically we have to add &NOTHING or &ANYTHING
-                like we do for an empty constructor as well.  */
-             return;
-           }
          default:;
          }
        break;
          default:;
          }
        break;
@@ -3458,19 +3277,7 @@ do_structure_copy (tree lhsop, tree rhsop)
   if (lhsp->type == DEREF
       || (lhsp->type == ADDRESSOF && lhsp->var == anything_id)
       || rhsp->type == DEREF)
   if (lhsp->type == DEREF
       || (lhsp->type == ADDRESSOF && lhsp->var == anything_id)
       || rhsp->type == DEREF)
-    {
-      if (lhsp->type == DEREF)
-       {
-         gcc_assert (VEC_length (ce_s, lhsc) == 1);
-         lhsp->offset = UNKNOWN_OFFSET;
-       }
-      if (rhsp->type == DEREF)
-       {
-         gcc_assert (VEC_length (ce_s, rhsc) == 1);
-         rhsp->offset = UNKNOWN_OFFSET;
-       }
-      process_all_all_constraints (lhsc, rhsc);
-    }
+    process_all_all_constraints (lhsc, rhsc);
   else if (lhsp->type == SCALAR
           && (rhsp->type == SCALAR
               || rhsp->type == ADDRESSOF))
   else if (lhsp->type == SCALAR
           && (rhsp->type == SCALAR
               || rhsp->type == ADDRESSOF))
@@ -3570,37 +3377,11 @@ make_escape_constraint (tree op)
   make_constraint_to (escaped_id, op);
 }
 
   make_constraint_to (escaped_id, op);
 }
 
-/* Add constraints to that the solution of VI is transitively closed.  */
-
-static void
-make_transitive_closure_constraints (varinfo_t vi)
-{
-  struct constraint_expr lhs, rhs;
-
-  /* VAR = *VAR;  */
-  lhs.type = SCALAR;
-  lhs.var = vi->id;
-  lhs.offset = 0;
-  rhs.type = DEREF;
-  rhs.var = vi->id;
-  rhs.offset = 0;
-  process_constraint (new_constraint (lhs, rhs));
-
-  /* VAR = VAR + UNKNOWN;  */
-  lhs.type = SCALAR;
-  lhs.var = vi->id;
-  lhs.offset = 0;
-  rhs.type = SCALAR;
-  rhs.var = vi->id;
-  rhs.offset = UNKNOWN_OFFSET;
-  process_constraint (new_constraint (lhs, rhs));
-}
-
-/* Create a new artificial heap variable with NAME.
-   Return the created variable.  */
+/* Create a new artificial heap variable with NAME and make a
+   constraint from it to LHS.  Return the created variable.  */
 
 static varinfo_t
 
 static varinfo_t
-make_heapvar_for (varinfo_t lhs, const char *name)
+make_constraint_from_heapvar (varinfo_t lhs, const char *name)
 {
   varinfo_t vi;
   tree heapvar = heapvar_lookup (lhs->decl, lhs->offset);
 {
   varinfo_t vi;
   tree heapvar = heapvar_lookup (lhs->decl, lhs->offset);
@@ -3619,7 +3400,7 @@ make_heapvar_for (varinfo_t lhs, const char *name)
 
   /* For global vars we need to add a heapvar to the list of referenced
      vars of a different function than it was created for originally.  */
 
   /* For global vars we need to add a heapvar to the list of referenced
      vars of a different function than it was created for originally.  */
-  if (cfun && gimple_referenced_vars (cfun))
+  if (gimple_referenced_vars (cfun))
     add_referenced_var (heapvar);
 
   vi = new_var_info (heapvar, name);
     add_referenced_var (heapvar);
 
   vi = new_var_info (heapvar, name);
@@ -3632,16 +3413,6 @@ make_heapvar_for (varinfo_t lhs, const char *name)
   vi->is_full_var = true;
   insert_vi_for_tree (heapvar, vi);
 
   vi->is_full_var = true;
   insert_vi_for_tree (heapvar, vi);
 
-  return vi;
-}
-
-/* Create a new artificial heap variable with NAME and make a
-   constraint from it to LHS.  Return the created variable.  */
-
-static varinfo_t
-make_constraint_from_heapvar (varinfo_t lhs, const char *name)
-{
-  varinfo_t vi = make_heapvar_for (lhs, name);
   make_constraint_from (lhs, vi->id);
 
   return vi;
   make_constraint_from (lhs, vi->id);
 
   return vi;
@@ -3662,52 +3433,6 @@ make_constraint_from_restrict (varinfo_t lhs, const char *name)
   vi->may_have_pointers = 0;
 }
 
   vi->may_have_pointers = 0;
 }
 
-/* In IPA mode there are varinfos for different aspects of reach
-   function designator.  One for the points-to set of the return
-   value, one for the variables that are clobbered by the function,
-   one for its uses and one for each parameter (including a single
-   glob for remaining variadic arguments).  */
-
-enum { fi_clobbers = 1, fi_uses = 2,
-       fi_static_chain = 3, fi_result = 4, fi_parm_base = 5 };
-
-/* Get a constraint for the requested part of a function designator FI
-   when operating in IPA mode.  */
-
-static struct constraint_expr
-get_function_part_constraint (varinfo_t fi, unsigned part)
-{
-  struct constraint_expr c;
-
-  gcc_assert (in_ipa_mode);
-
-  if (fi->id == anything_id)
-    {
-      /* ???  We probably should have a ANYFN special variable.  */
-      c.var = anything_id;
-      c.offset = 0;
-      c.type = SCALAR;
-    }
-  else if (TREE_CODE (fi->decl) == FUNCTION_DECL)
-    {
-      varinfo_t ai = first_vi_for_offset (fi, part);
-      if (ai)
-       c.var = ai->id;
-      else
-       c.var = anything_id;
-      c.offset = 0;
-      c.type = SCALAR;
-    }
-  else
-    {
-      c.var = fi->id;
-      c.offset = part;
-      c.type = DEREF;
-    }
-
-  return c;
-}
-
 /* For non-IPA mode, generate constraints necessary for a call on the
    RHS.  */
 
 /* For non-IPA mode, generate constraints necessary for a call on the
    RHS.  */
 
@@ -3716,61 +3441,17 @@ handle_rhs_call (gimple stmt, VEC(ce_s, heap) **results)
 {
   struct constraint_expr rhsc;
   unsigned i;
 {
   struct constraint_expr rhsc;
   unsigned i;
-  bool returns_uses = false;
 
   for (i = 0; i < gimple_call_num_args (stmt); ++i)
     {
       tree arg = gimple_call_arg (stmt, i);
 
   for (i = 0; i < gimple_call_num_args (stmt); ++i)
     {
       tree arg = gimple_call_arg (stmt, i);
-      int flags = gimple_call_arg_flags (stmt, i);
-
-      /* If the argument is not used or it does not contain pointers
-        we can ignore it.  */
-      if ((flags & EAF_UNUSED)
-         || !could_have_pointers (arg))
-       continue;
 
 
-      /* As we compute ESCAPED context-insensitive we do not gain
-         any precision with just EAF_NOCLOBBER but not EAF_NOESCAPE
-        set.  The argument would still get clobbered through the
-        escape solution.
-        ???  We might get away with less (and more precise) constraints
-        if using a temporary for transitively closing things.  */
-      if ((flags & EAF_NOCLOBBER)
-          && (flags & EAF_NOESCAPE))
-       {
-         varinfo_t uses = get_call_use_vi (stmt);
-         if (!(flags & EAF_DIRECT))
-           make_transitive_closure_constraints (uses);
-         make_constraint_to (uses->id, arg);
-         returns_uses = true;
-       }
-      else if (flags & EAF_NOESCAPE)
-       {
-         varinfo_t uses = get_call_use_vi (stmt);
-         varinfo_t clobbers = get_call_clobber_vi (stmt);
-         if (!(flags & EAF_DIRECT))
-           {
-             make_transitive_closure_constraints (uses);
-             make_transitive_closure_constraints (clobbers);
-           }
-         make_constraint_to (uses->id, arg);
-         make_constraint_to (clobbers->id, arg);
-         returns_uses = true;
-       }
-      else
+      /* Find those pointers being passed, and make sure they end up
+        pointing to anything.  */
+      if (could_have_pointers (arg))
        make_escape_constraint (arg);
     }
 
        make_escape_constraint (arg);
     }
 
-  /* If we added to the calls uses solution make sure we account for
-     pointers to it to be returned.  */
-  if (returns_uses)
-    {
-      rhsc.var = get_call_use_vi (stmt)->id;
-      rhsc.offset = 0;
-      rhsc.type = SCALAR;
-      VEC_safe_push (ce_s, heap, *results, &rhsc);
-    }
-
   /* The static chain escapes as well.  */
   if (gimple_call_chain (stmt))
     make_escape_constraint (gimple_call_chain (stmt));
   /* The static chain escapes as well.  */
   if (gimple_call_chain (stmt))
     make_escape_constraint (gimple_call_chain (stmt));
@@ -3803,63 +3484,44 @@ handle_rhs_call (gimple stmt, VEC(ce_s, heap) **results)
    the LHS point to global and escaped variables.  */
 
 static void
    the LHS point to global and escaped variables.  */
 
 static void
-handle_lhs_call (gimple stmt, tree lhs, int flags, VEC(ce_s, heap) *rhsc,
-                tree fndecl)
+handle_lhs_call (tree lhs, int flags, VEC(ce_s, heap) *rhsc, tree fndecl)
 {
   VEC(ce_s, heap) *lhsc = NULL;
 
   get_constraint_for (lhs, &lhsc);
 {
   VEC(ce_s, heap) *lhsc = NULL;
 
   get_constraint_for (lhs, &lhsc);
-  /* If the store is to a global decl make sure to
-     add proper escape constraints.  */
-  lhs = get_base_address (lhs);
-  if (lhs
-      && DECL_P (lhs)
-      && is_global_var (lhs))
-    {
-      struct constraint_expr tmpc;
-      tmpc.var = escaped_id;
-      tmpc.offset = 0;
-      tmpc.type = SCALAR;
-      VEC_safe_push (ce_s, heap, lhsc, &tmpc);
-    }
 
 
-  /* If the call returns an argument unmodified override the rhs
-     constraints.  */
-  flags = gimple_call_return_flags (stmt);
-  if (flags & ERF_RETURNS_ARG
-      && (flags & ERF_RETURN_ARG_MASK) < gimple_call_num_args (stmt))
-    {
-      tree arg;
-      rhsc = NULL;
-      arg = gimple_call_arg (stmt, flags & ERF_RETURN_ARG_MASK);
-      get_constraint_for (arg, &rhsc);
-      process_all_all_constraints (lhsc, rhsc);
-      VEC_free (ce_s, heap, rhsc);
-    }
-  else if (flags & ERF_NOALIAS)
+  if (flags & ECF_MALLOC)
     {
       varinfo_t vi;
     {
       varinfo_t vi;
-      struct constraint_expr tmpc;
-      rhsc = NULL;
-      vi = make_heapvar_for (get_vi_for_tree (lhs), "HEAP");
+      vi = make_constraint_from_heapvar (get_vi_for_tree (lhs), "HEAP");
       /* We delay marking allocated storage global until we know if
          it escapes.  */
       DECL_EXTERNAL (vi->decl) = 0;
       vi->is_global_var = 0;
       /* If this is not a real malloc call assume the memory was
       /* We delay marking allocated storage global until we know if
          it escapes.  */
       DECL_EXTERNAL (vi->decl) = 0;
       vi->is_global_var = 0;
       /* If this is not a real malloc call assume the memory was
-        initialized and thus may point to global memory.  All
+         initialized and thus may point to global memory.  All
         builtin functions with the malloc attribute behave in a sane way.  */
       if (!fndecl
          || DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_NORMAL)
        make_constraint_from (vi, nonlocal_id);
         builtin functions with the malloc attribute behave in a sane way.  */
       if (!fndecl
          || DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_NORMAL)
        make_constraint_from (vi, nonlocal_id);
-      tmpc.var = vi->id;
-      tmpc.offset = 0;
-      tmpc.type = ADDRESSOF;
-      VEC_safe_push (ce_s, heap, rhsc, &tmpc);
     }
     }
-
-  process_all_all_constraints (lhsc, rhsc);
-
+  else if (VEC_length (ce_s, rhsc) > 0)
+    {
+      /* If the store is to a global decl make sure to
+        add proper escape constraints.  */
+      lhs = get_base_address (lhs);
+      if (lhs
+         && DECL_P (lhs)
+         && is_global_var (lhs))
+       {
+         struct constraint_expr tmpc;
+         tmpc.var = escaped_id;
+         tmpc.offset = 0;
+         tmpc.type = SCALAR;
+         VEC_safe_push (ce_s, heap, lhsc, &tmpc);
+       }
+      process_all_all_constraints (lhsc, rhsc);
+    }
   VEC_free (ce_s, heap, lhsc);
 }
 
   VEC_free (ce_s, heap, lhsc);
 }
 
@@ -3876,10 +3538,8 @@ handle_const_call (gimple stmt, VEC(ce_s, heap) **results)
      as the static chain is concerned.  */
   if (gimple_call_chain (stmt))
     {
      as the static chain is concerned.  */
   if (gimple_call_chain (stmt))
     {
-      varinfo_t uses = get_call_use_vi (stmt);
-      make_transitive_closure_constraints (uses);
-      make_constraint_to (uses->id, gimple_call_chain (stmt));
-      rhsc.var = uses->id;
+      make_constraint_to (callused_id, gimple_call_chain (stmt));
+      rhsc.var = callused_id;
       rhsc.offset = 0;
       rhsc.type = SCALAR;
       VEC_safe_push (ce_s, heap, *results, &rhsc);
       rhsc.offset = 0;
       rhsc.type = SCALAR;
       VEC_safe_push (ce_s, heap, *results, &rhsc);
@@ -3917,7 +3577,7 @@ handle_pure_call (gimple stmt, VEC(ce_s, heap) **results)
 {
   struct constraint_expr rhsc;
   unsigned i;
 {
   struct constraint_expr rhsc;
   unsigned i;
-  varinfo_t uses = NULL;
+  bool need_callused = false;
 
   /* Memory reached from pointer arguments is call-used.  */
   for (i = 0; i < gimple_call_num_args (stmt); ++i)
 
   /* Memory reached from pointer arguments is call-used.  */
   for (i = 0; i < gimple_call_num_args (stmt); ++i)
@@ -3926,30 +3586,22 @@ handle_pure_call (gimple stmt, VEC(ce_s, heap) **results)
 
       if (could_have_pointers (arg))
        {
 
       if (could_have_pointers (arg))
        {
-         if (!uses)
-           {
-             uses = get_call_use_vi (stmt);
-             make_transitive_closure_constraints (uses);
-           }
-         make_constraint_to (uses->id, arg);
+         make_constraint_to (callused_id, arg);
+         need_callused = true;
        }
     }
 
   /* The static chain is used as well.  */
   if (gimple_call_chain (stmt))
     {
        }
     }
 
   /* The static chain is used as well.  */
   if (gimple_call_chain (stmt))
     {
-      if (!uses)
-       {
-         uses = get_call_use_vi (stmt);
-         make_transitive_closure_constraints (uses);
-       }
-      make_constraint_to (uses->id, gimple_call_chain (stmt));
+      make_constraint_to (callused_id, gimple_call_chain (stmt));
+      need_callused = true;
     }
 
     }
 
-  /* Pure functions may return call-used and nonlocal memory.  */
-  if (uses)
+  /* Pure functions may return callused and nonlocal memory.  */
+  if (need_callused)
     {
     {
-      rhsc.var = uses->id;
+      rhsc.var = callused_id;
       rhsc.offset = 0;
       rhsc.type = SCALAR;
       VEC_safe_push (ce_s, heap, *results, &rhsc);
       rhsc.offset = 0;
       rhsc.type = SCALAR;
       VEC_safe_push (ce_s, heap, *results, &rhsc);
@@ -3960,40 +3612,6 @@ handle_pure_call (gimple stmt, VEC(ce_s, heap) **results)
   VEC_safe_push (ce_s, heap, *results, &rhsc);
 }
 
   VEC_safe_push (ce_s, heap, *results, &rhsc);
 }
 
-
-/* Return the varinfo for the callee of CALL.  */
-
-static varinfo_t
-get_fi_for_callee (gimple call)
-{
-  tree decl;
-
-  /* If we can directly resolve the function being called, do so.
-     Otherwise, it must be some sort of indirect expression that
-     we should still be able to handle.  */
-  decl = gimple_call_fndecl (call);
-  if (decl)
-    return get_vi_for_tree (decl);
-
-  decl = gimple_call_fn (call);
-  /* The function can be either an SSA name pointer or,
-     worse, an OBJ_TYPE_REF.  In this case we have no
-     clue and should be getting ANYFN (well, ANYTHING for now).  */
-  if (TREE_CODE (decl) == SSA_NAME)
-    {
-      if (TREE_CODE (decl) == SSA_NAME
-         && TREE_CODE (SSA_NAME_VAR (decl)) == PARM_DECL
-         && SSA_NAME_IS_DEFAULT_DEF (decl))
-       decl = SSA_NAME_VAR (decl);
-      return get_vi_for_tree (decl);
-    }
-  else if (TREE_CODE (decl) == INTEGER_CST
-          || TREE_CODE (decl) == OBJ_TYPE_REF)
-    return get_varinfo (anything_id);
-  else
-    gcc_unreachable ();
-}
-
 /* Walk statement T setting up aliasing constraints according to the
    references found in T.  This function is the main part of the
    constraint builder.  AI points to auxiliary alias information used
 /* Walk statement T setting up aliasing constraints according to the
    references found in T.  This function is the main part of the
    constraint builder.  AI points to auxiliary alias information used
@@ -4006,7 +3624,6 @@ find_func_aliases (gimple origt)
   VEC(ce_s, heap) *lhsc = NULL;
   VEC(ce_s, heap) *rhsc = NULL;
   struct constraint_expr *c;
   VEC(ce_s, heap) *lhsc = NULL;
   VEC(ce_s, heap) *rhsc = NULL;
   struct constraint_expr *c;
-  varinfo_t fi;
 
   /* Now build constraints expressions.  */
   if (gimple_code (t) == GIMPLE_PHI)
 
   /* Now build constraints expressions.  */
   if (gimple_code (t) == GIMPLE_PHI)
@@ -4159,88 +3776,6 @@ find_func_aliases (gimple origt)
          case BUILT_IN_REMQUOL:
          case BUILT_IN_FREE:
            return;
          case BUILT_IN_REMQUOL:
          case BUILT_IN_FREE:
            return;
-         /* Trampolines are special - they set up passing the static
-            frame.  */
-         case BUILT_IN_INIT_TRAMPOLINE:
-           {
-             tree tramp = gimple_call_arg (t, 0);
-             tree nfunc = gimple_call_arg (t, 1);
-             tree frame = gimple_call_arg (t, 2);
-             unsigned i;
-             struct constraint_expr lhs, *rhsp;
-             if (in_ipa_mode)
-               {
-                 varinfo_t nfi = NULL;
-                 gcc_assert (TREE_CODE (nfunc) == ADDR_EXPR);
-                 nfi = lookup_vi_for_tree (TREE_OPERAND (nfunc, 0));
-                 if (nfi)
-                   {
-                     lhs = get_function_part_constraint (nfi, fi_static_chain);
-                     get_constraint_for (frame, &rhsc);
-                     for (i = 0; VEC_iterate (ce_s, rhsc, i, rhsp); ++i)
-                       process_constraint (new_constraint (lhs, *rhsp));
-                     VEC_free (ce_s, heap, rhsc);
-
-                     /* Make the frame point to the function for
-                        the trampoline adjustment call.  */
-                     get_constraint_for (tramp, &lhsc);
-                     do_deref (&lhsc);
-                     get_constraint_for (nfunc, &rhsc);
-                     process_all_all_constraints (lhsc, rhsc);
-                     VEC_free (ce_s, heap, rhsc);
-                     VEC_free (ce_s, heap, lhsc);
-
-                     return;
-                   }
-               }
-             /* Else fallthru to generic handling which will let
-                the frame escape.  */
-             break;
-           }
-         case BUILT_IN_ADJUST_TRAMPOLINE:
-           {
-             tree tramp = gimple_call_arg (t, 0);
-             tree res = gimple_call_lhs (t);
-             if (in_ipa_mode && res)
-               {
-                 get_constraint_for (res, &lhsc);
-                 get_constraint_for (tramp, &rhsc);
-                 do_deref (&rhsc);
-                 process_all_all_constraints (lhsc, rhsc);
-                 VEC_free (ce_s, heap, rhsc);
-                 VEC_free (ce_s, heap, lhsc);
-               }
-             return;
-           }
-         /* Variadic argument handling needs to be handled in IPA
-            mode as well.  */
-         case BUILT_IN_VA_START:
-           {
-             if (in_ipa_mode)
-               {
-                 tree valist = gimple_call_arg (t, 0);
-                 struct constraint_expr rhs, *lhsp;
-                 unsigned i;
-                 /* The va_list gets access to pointers in variadic
-                    arguments.  */
-                 fi = lookup_vi_for_tree (cfun->decl);
-                 gcc_assert (fi != NULL);
-                 get_constraint_for (valist, &lhsc);
-                 do_deref (&lhsc);
-                 rhs = get_function_part_constraint (fi, ~0);
-                 rhs.type = ADDRESSOF;
-                 for (i = 0; VEC_iterate (ce_s, lhsc, i, lhsp); ++i)
-                   process_constraint (new_constraint (*lhsp, rhs));
-                 VEC_free (ce_s, heap, lhsc);
-                 /* va_list is clobbered.  */
-                 make_constraint_to (get_call_clobber_vi (t)->id, valist);
-                 return;
-               }
-             break;
-           }
-         /* va_end doesn't have any effect that matters.  */
-         case BUILT_IN_VA_END:
-           return;
          /* printf-style functions may have hooks to set pointers to
             point to somewhere into the generated string.  Leave them
             for a later excercise...  */
          /* printf-style functions may have hooks to set pointers to
             point to somewhere into the generated string.  Leave them
             for a later excercise...  */
@@ -4249,8 +3784,7 @@ find_func_aliases (gimple origt)
          }
       if (!in_ipa_mode
          || (fndecl
          }
       if (!in_ipa_mode
          || (fndecl
-             && (!(fi = lookup_vi_for_tree (fndecl))
-                 || !fi->is_fn_info)))
+             && !lookup_vi_for_tree (fndecl)))
        {
          VEC(ce_s, heap) *rhsc = NULL;
          int flags = gimple_call_flags (t);
        {
          VEC(ce_s, heap) *rhsc = NULL;
          int flags = gimple_call_flags (t);
@@ -4272,15 +3806,30 @@ find_func_aliases (gimple origt)
            handle_rhs_call (t, &rhsc);
          if (gimple_call_lhs (t)
              && could_have_pointers (gimple_call_lhs (t)))
            handle_rhs_call (t, &rhsc);
          if (gimple_call_lhs (t)
              && could_have_pointers (gimple_call_lhs (t)))
-           handle_lhs_call (t, gimple_call_lhs (t), flags, rhsc, fndecl);
+           handle_lhs_call (gimple_call_lhs (t), flags, rhsc, fndecl);
          VEC_free (ce_s, heap, rhsc);
        }
       else
        {
          tree lhsop;
          VEC_free (ce_s, heap, rhsc);
        }
       else
        {
          tree lhsop;
-         unsigned j;
+         varinfo_t fi;
+         int i = 1;
+         size_t j;
+         tree decl;
+
+         lhsop = gimple_call_lhs (t);
+         decl = gimple_call_fndecl (t);
 
 
-         fi = get_fi_for_callee (t);
+         /* If we can directly resolve the function being called, do so.
+            Otherwise, it must be some sort of indirect expression that
+            we should still be able to handle.  */
+         if (decl)
+           fi = get_vi_for_tree (decl);
+         else
+           {
+             decl = gimple_call_fn (t);
+             fi = get_vi_for_tree (decl);
+           }
 
          /* Assign all the passed arguments to the appropriate incoming
             parameters of the function.  */
 
          /* Assign all the passed arguments to the appropriate incoming
             parameters of the function.  */
@@ -4290,77 +3839,58 @@ find_func_aliases (gimple origt)
              struct constraint_expr *rhsp;
              tree arg = gimple_call_arg (t, j);
 
              struct constraint_expr *rhsp;
              tree arg = gimple_call_arg (t, j);
 
-             if (!could_have_pointers (arg))
-               continue;
-
              get_constraint_for (arg, &rhsc);
              get_constraint_for (arg, &rhsc);
-             lhs = get_function_part_constraint (fi, fi_parm_base + j);
+             if (TREE_CODE (decl) != FUNCTION_DECL)
+               {
+                 lhs.type = DEREF;
+                 lhs.var = fi->id;
+                 lhs.offset = i;
+               }
+             else
+               {
+                 lhs.type = SCALAR;
+                 lhs.var = first_vi_for_offset (fi, i)->id;
+                 lhs.offset = 0;
+               }
              while (VEC_length (ce_s, rhsc) != 0)
                {
                  rhsp = VEC_last (ce_s, rhsc);
                  process_constraint (new_constraint (lhs, *rhsp));
                  VEC_pop (ce_s, rhsc);
                }
              while (VEC_length (ce_s, rhsc) != 0)
                {
                  rhsp = VEC_last (ce_s, rhsc);
                  process_constraint (new_constraint (lhs, *rhsp));
                  VEC_pop (ce_s, rhsc);
                }
+             i++;
            }
 
          /* If we are returning a value, assign it to the result.  */
            }
 
          /* If we are returning a value, assign it to the result.  */
-         lhsop = gimple_call_lhs (t);
-         if (lhsop
-             && type_could_have_pointers (TREE_TYPE (lhsop)))
+         if (lhsop)
            {
              struct constraint_expr rhs;
              struct constraint_expr *lhsp;
            {
              struct constraint_expr rhs;
              struct constraint_expr *lhsp;
+             unsigned int j = 0;
 
              get_constraint_for (lhsop, &lhsc);
 
              get_constraint_for (lhsop, &lhsc);
-             rhs = get_function_part_constraint (fi, fi_result);
-             if (fndecl
-                 && DECL_RESULT (fndecl)
-                 && DECL_BY_REFERENCE (DECL_RESULT (fndecl)))
+             if (TREE_CODE (decl) != FUNCTION_DECL)
                {
                {
-                 VEC(ce_s, heap) *tem = NULL;
-                 VEC_safe_push (ce_s, heap, tem, &rhs);
-                 do_deref (&tem);
-                 rhs = *VEC_index (ce_s, tem, 0);
-                 VEC_free(ce_s, heap, tem);
+                 rhs.type = DEREF;
+                 rhs.var = fi->id;
+                 rhs.offset = i;
+               }
+             else
+               {
+                 rhs.type = SCALAR;
+                 rhs.var = first_vi_for_offset (fi, i)->id;
+                 rhs.offset = 0;
                }
              for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
                process_constraint (new_constraint (*lhsp, rhs));
            }
                }
              for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
                process_constraint (new_constraint (*lhsp, rhs));
            }
-
-         /* If we pass the result decl by reference, honor that.  */
-         if (lhsop
-             && fndecl
-             && DECL_RESULT (fndecl)
-             && DECL_BY_REFERENCE (DECL_RESULT (fndecl)))
-           {
-             struct constraint_expr lhs;
-             struct constraint_expr *rhsp;
-
-             get_constraint_for_address_of (lhsop, &rhsc);
-             lhs = get_function_part_constraint (fi, fi_result);
-             for (j = 0; VEC_iterate (ce_s, rhsc, j, rhsp); j++)
-               process_constraint (new_constraint (lhs, *rhsp));
-             VEC_free (ce_s, heap, rhsc);
-           }
-
-         /* If we use a static chain, pass it along.  */
-         if (gimple_call_chain (t))
-           {
-             struct constraint_expr lhs;
-             struct constraint_expr *rhsp;
-
-             get_constraint_for (gimple_call_chain (t), &rhsc);
-             lhs = get_function_part_constraint (fi, fi_static_chain);
-             for (j = 0; VEC_iterate (ce_s, rhsc, j, rhsp); j++)
-               process_constraint (new_constraint (lhs, *rhsp));
-           }
        }
     }
   /* Otherwise, just a regular assignment statement.  Only care about
      operations with pointer result, others are dealt with as escape
      points if they have pointer operands.  */
   else if (is_gimple_assign (t)
        }
     }
   /* Otherwise, just a regular assignment statement.  Only care about
      operations with pointer result, others are dealt with as escape
      points if they have pointer operands.  */
   else if (is_gimple_assign (t)
-          && type_could_have_pointers (TREE_TYPE (gimple_assign_lhs (t))))
+          && could_have_pointers (gimple_assign_lhs (t)))
     {
       /* Otherwise, just a regular assignment statement.  */
       tree lhsop = gimple_assign_lhs (t);
     {
       /* Otherwise, just a regular assignment statement.  */
       tree lhsop = gimple_assign_lhs (t);
@@ -4393,9 +3923,7 @@ find_func_aliases (gimple origt)
       /* If there is a store to a global variable the rhs escapes.  */
       if ((lhsop = get_base_address (lhsop)) != NULL_TREE
          && DECL_P (lhsop)
       /* If there is a store to a global variable the rhs escapes.  */
       if ((lhsop = get_base_address (lhsop)) != NULL_TREE
          && DECL_P (lhsop)
-         && is_global_var (lhsop)
-         && (!in_ipa_mode
-             || DECL_EXTERNAL (lhsop) || TREE_PUBLIC (lhsop)))
+         && is_global_var (lhsop))
        make_escape_constraint (rhsop);
       /* If this is a conversion of a non-restrict pointer to a
         restrict pointer track it with a new heapvar.  */
        make_escape_constraint (rhsop);
       /* If this is a conversion of a non-restrict pointer to a
         restrict pointer track it with a new heapvar.  */
@@ -4419,22 +3947,7 @@ find_func_aliases (gimple origt)
           && gimple_return_retval (t) != NULL_TREE
           && could_have_pointers (gimple_return_retval (t)))
     {
           && gimple_return_retval (t) != NULL_TREE
           && could_have_pointers (gimple_return_retval (t)))
     {
-      fi = NULL;
-      if (!in_ipa_mode
-         || !(fi = get_vi_for_tree (cfun->decl)))
-       make_escape_constraint (gimple_return_retval (t));
-      else if (in_ipa_mode
-              && fi != NULL)
-       {
-         struct constraint_expr lhs ;
-         struct constraint_expr *rhsp;
-         unsigned i;
-
-         lhs = get_function_part_constraint (fi, fi_result);
-         get_constraint_for (gimple_return_retval (t), &rhsc);
-         for (i = 0; VEC_iterate (ce_s, rhsc, i, rhsp); i++)
-           process_constraint (new_constraint (lhs, *rhsp));
-       }
+      make_escape_constraint (gimple_return_retval (t));
     }
   /* Handle asms conservatively by adding escape constraints to everything.  */
   else if (gimple_code (t) == GIMPLE_ASM)
     }
   /* Handle asms conservatively by adding escape constraints to everything.  */
   else if (gimple_code (t) == GIMPLE_ASM)
@@ -4491,8 +4004,8 @@ find_func_aliases (gimple origt)
          if (!allows_reg && allows_mem)
            make_escape_constraint (build_fold_addr_expr (op));
          /* Strictly we'd only need the constraint to ESCAPED if
          if (!allows_reg && allows_mem)
            make_escape_constraint (build_fold_addr_expr (op));
          /* Strictly we'd only need the constraint to ESCAPED if
-            the asm clobbers memory, otherwise using something
-            along the lines of per-call clobbers/uses would be enough.  */
+            the asm clobbers memory, otherwise using CALLUSED
+            would be enough.  */
          else if (op && could_have_pointers (op))
            make_escape_constraint (op);
        }
          else if (op && could_have_pointers (op))
            make_escape_constraint (op);
        }
@@ -4503,297 +4016,20 @@ find_func_aliases (gimple origt)
 }
 
 
 }
 
 
-/* Create a constraint adding to the clobber set of FI the memory
-   pointed to by PTR.  */
-
-static void
-process_ipa_clobber (varinfo_t fi, tree ptr)
-{
-  VEC(ce_s, heap) *ptrc = NULL;
-  struct constraint_expr *c, lhs;
-  unsigned i;
-  get_constraint_for (ptr, &ptrc);
-  lhs = get_function_part_constraint (fi, fi_clobbers);
-  for (i = 0; VEC_iterate (ce_s, ptrc, i, c); i++)
-    process_constraint (new_constraint (lhs, *c));
-  VEC_free (ce_s, heap, ptrc);
-}
-
-/* Walk statement T setting up clobber and use constraints according to the
-   references found in T.  This function is a main part of the
-   IPA constraint builder.  */
+/* Find the first varinfo in the same variable as START that overlaps with
+   OFFSET.  Return NULL if we can't find one.  */
 
 
-static void
-find_func_clobbers (gimple origt)
+static varinfo_t
+first_vi_for_offset (varinfo_t start, unsigned HOST_WIDE_INT offset)
 {
 {
-  gimple t = origt;
-  VEC(ce_s, heap) *lhsc = NULL;
-  VEC(ce_s, heap) *rhsc = NULL;
-  varinfo_t fi;
+  /* If the offset is outside of the variable, bail out.  */
+  if (offset >= start->fullsize)
+    return NULL;
 
 
-  /* Add constraints for clobbered/used in IPA mode.
-     We are not interested in what automatic variables are clobbered
-     or used as we only use the information in the caller to which
-     they do not escape.  */
-  gcc_assert (in_ipa_mode);
-
-  /* If the stmt refers to memory in any way it better had a VUSE.  */
-  if (gimple_vuse (t) == NULL_TREE)
-    return;
-
-  /* We'd better have function information for the current function.  */
-  fi = lookup_vi_for_tree (cfun->decl);
-  gcc_assert (fi != NULL);
-
-  /* Account for stores in assignments and calls.  */
-  if (gimple_vdef (t) != NULL_TREE
-      && gimple_has_lhs (t))
-    {
-      tree lhs = gimple_get_lhs (t);
-      tree tem = lhs;
-      while (handled_component_p (tem))
-       tem = TREE_OPERAND (tem, 0);
-      if ((DECL_P (tem)
-          && !auto_var_in_fn_p (tem, cfun->decl))
-         || INDIRECT_REF_P (tem))
-       {
-         struct constraint_expr lhsc, *rhsp;
-         unsigned i;
-         lhsc = get_function_part_constraint (fi, fi_clobbers);
-         get_constraint_for_address_of (lhs, &rhsc);
-         for (i = 0; VEC_iterate (ce_s, rhsc, i, rhsp); i++)
-           process_constraint (new_constraint (lhsc, *rhsp));
-         VEC_free (ce_s, heap, rhsc);
-       }
-    }
-
-  /* Account for uses in assigments and returns.  */
-  if (gimple_assign_single_p (t)
-      || (gimple_code (t) == GIMPLE_RETURN
-         && gimple_return_retval (t) != NULL_TREE))
-    {
-      tree rhs = (gimple_assign_single_p (t)
-                 ? gimple_assign_rhs1 (t) : gimple_return_retval (t));
-      tree tem = rhs;
-      while (handled_component_p (tem))
-       tem = TREE_OPERAND (tem, 0);
-      if ((DECL_P (tem)
-          && !auto_var_in_fn_p (tem, cfun->decl))
-         || INDIRECT_REF_P (tem))
-       {
-         struct constraint_expr lhs, *rhsp;
-         unsigned i;
-         lhs = get_function_part_constraint (fi, fi_uses);
-         get_constraint_for_address_of (rhs, &rhsc);
-         for (i = 0; VEC_iterate (ce_s, rhsc, i, rhsp); i++)
-           process_constraint (new_constraint (lhs, *rhsp));
-         VEC_free (ce_s, heap, rhsc);
-       }
-    }
-
-  if (is_gimple_call (t))
-    {
-      varinfo_t cfi = NULL;
-      tree decl = gimple_call_fndecl (t);
-      struct constraint_expr lhs, rhs;
-      unsigned i, j;
-
-      /* For builtins we do not have separate function info.  For those
-        we do not generate escapes for we have to generate clobbers/uses.  */
-      if (decl
-         && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
-       switch (DECL_FUNCTION_CODE (decl))
-         {
-         /* The following functions use and clobber memory pointed to
-            by their arguments.  */
-         case BUILT_IN_STRCPY:
-         case BUILT_IN_STRNCPY:
-         case BUILT_IN_BCOPY:
-         case BUILT_IN_MEMCPY:
-         case BUILT_IN_MEMMOVE:
-         case BUILT_IN_MEMPCPY:
-         case BUILT_IN_STPCPY:
-         case BUILT_IN_STPNCPY:
-         case BUILT_IN_STRCAT:
-         case BUILT_IN_STRNCAT:
-           {
-             tree dest = gimple_call_arg (t, (DECL_FUNCTION_CODE (decl)
-                                              == BUILT_IN_BCOPY ? 1 : 0));
-             tree src = gimple_call_arg (t, (DECL_FUNCTION_CODE (decl)
-                                             == BUILT_IN_BCOPY ? 0 : 1));
-             unsigned i;
-             struct constraint_expr *rhsp, *lhsp;
-             get_constraint_for_ptr_offset (dest, NULL_TREE, &lhsc);
-             lhs = get_function_part_constraint (fi, fi_clobbers);
-             for (i = 0; VEC_iterate (ce_s, lhsc, i, lhsp); i++)
-               process_constraint (new_constraint (lhs, *lhsp));
-             VEC_free (ce_s, heap, lhsc);
-             get_constraint_for_ptr_offset (src, NULL_TREE, &rhsc);
-             lhs = get_function_part_constraint (fi, fi_uses);
-             for (i = 0; VEC_iterate (ce_s, rhsc, i, rhsp); i++)
-               process_constraint (new_constraint (lhs, *rhsp));
-             VEC_free (ce_s, heap, rhsc);
-             return;
-           }
-         /* The following function clobbers memory pointed to by
-            its argument.  */
-         case BUILT_IN_MEMSET:
-           {
-             tree dest = gimple_call_arg (t, 0);
-             unsigned i;
-             ce_s *lhsp;
-             get_constraint_for_ptr_offset (dest, NULL_TREE, &lhsc);
-             lhs = get_function_part_constraint (fi, fi_clobbers);
-             for (i = 0; VEC_iterate (ce_s, lhsc, i, lhsp); i++)
-               process_constraint (new_constraint (lhs, *lhsp));
-             VEC_free (ce_s, heap, lhsc);
-             return;
-           }
-         /* The following functions clobber their second and third
-            arguments.  */
-         case BUILT_IN_SINCOS:
-         case BUILT_IN_SINCOSF:
-         case BUILT_IN_SINCOSL:
-           {
-             process_ipa_clobber (fi, gimple_call_arg (t, 1));
-             process_ipa_clobber (fi, gimple_call_arg (t, 2));
-             return;
-           }
-         /* The following functions clobber their second argument.  */
-         case BUILT_IN_FREXP:
-         case BUILT_IN_FREXPF:
-         case BUILT_IN_FREXPL:
-         case BUILT_IN_LGAMMA_R:
-         case BUILT_IN_LGAMMAF_R:
-         case BUILT_IN_LGAMMAL_R:
-         case BUILT_IN_GAMMA_R:
-         case BUILT_IN_GAMMAF_R:
-         case BUILT_IN_GAMMAL_R:
-         case BUILT_IN_MODF:
-         case BUILT_IN_MODFF:
-         case BUILT_IN_MODFL:
-           {
-             process_ipa_clobber (fi, gimple_call_arg (t, 1));
-             return;
-           }
-         /* The following functions clobber their third argument.  */
-         case BUILT_IN_REMQUO:
-         case BUILT_IN_REMQUOF:
-         case BUILT_IN_REMQUOL:
-           {
-             process_ipa_clobber (fi, gimple_call_arg (t, 2));
-             return;
-           }
-         /* The following functions neither read nor clobber memory.  */
-         case BUILT_IN_FREE:
-           return;
-         /* Trampolines are of no interest to us.  */
-         case BUILT_IN_INIT_TRAMPOLINE:
-         case BUILT_IN_ADJUST_TRAMPOLINE:
-           return;
-         case BUILT_IN_VA_START:
-         case BUILT_IN_VA_END:
-           return;
-         /* printf-style functions may have hooks to set pointers to
-            point to somewhere into the generated string.  Leave them
-            for a later excercise...  */
-         default:
-           /* Fallthru to general call handling.  */;
-         }
-
-      /* Parameters passed by value are used.  */
-      lhs = get_function_part_constraint (fi, fi_uses);
-      for (i = 0; i < gimple_call_num_args (t); i++)
-       {
-         struct constraint_expr *rhsp;
-         tree arg = gimple_call_arg (t, i);
-
-         if (TREE_CODE (arg) == SSA_NAME
-             || is_gimple_min_invariant (arg))
-           continue;
-
-         get_constraint_for_address_of (arg, &rhsc);
-         for (j = 0; VEC_iterate (ce_s, rhsc, j, rhsp); j++)
-           process_constraint (new_constraint (lhs, *rhsp));
-         VEC_free (ce_s, heap, rhsc);
-       }
-
-      /* Build constraints for propagating clobbers/uses along the
-        callgraph edges.  */
-      cfi = get_fi_for_callee (t);
-      if (cfi->id == anything_id)
-       {
-         if (gimple_vdef (t))
-           make_constraint_from (first_vi_for_offset (fi, fi_clobbers),
-                                 anything_id);
-         make_constraint_from (first_vi_for_offset (fi, fi_uses),
-                               anything_id);
-         return;
-       }
-
-      /* For callees without function info (that's external functions),
-        ESCAPED is clobbered and used.  */
-      if (gimple_call_fndecl (t)
-         && !cfi->is_fn_info)
-       {
-         varinfo_t vi;
-
-         if (gimple_vdef (t))
-           make_copy_constraint (first_vi_for_offset (fi, fi_clobbers),
-                                 escaped_id);
-         make_copy_constraint (first_vi_for_offset (fi, fi_uses), escaped_id);
-
-         /* Also honor the call statement use/clobber info.  */
-         if ((vi = lookup_call_clobber_vi (t)) != NULL)
-           make_copy_constraint (first_vi_for_offset (fi, fi_clobbers),
-                                 vi->id);
-         if ((vi = lookup_call_use_vi (t)) != NULL)
-           make_copy_constraint (first_vi_for_offset (fi, fi_uses),
-                                 vi->id);
-         return;
-       }
-
-      /* Otherwise the caller clobbers and uses what the callee does.
-        ???  This should use a new complex constraint that filters
-        local variables of the callee.  */
-      if (gimple_vdef (t))
-       {
-         lhs = get_function_part_constraint (fi, fi_clobbers);
-         rhs = get_function_part_constraint (cfi, fi_clobbers);
-         process_constraint (new_constraint (lhs, rhs));
-       }
-      lhs = get_function_part_constraint (fi, fi_uses);
-      rhs = get_function_part_constraint (cfi, fi_uses);
-      process_constraint (new_constraint (lhs, rhs));
-    }
-  else if (gimple_code (t) == GIMPLE_ASM)
-    {
-      /* ???  Ick.  We can do better.  */
-      if (gimple_vdef (t))
-       make_constraint_from (first_vi_for_offset (fi, fi_clobbers),
-                             anything_id);
-      make_constraint_from (first_vi_for_offset (fi, fi_uses),
-                           anything_id);
-    }
-
-  VEC_free (ce_s, heap, rhsc);
-}
-
-
-/* Find the first varinfo in the same variable as START that overlaps with
-   OFFSET.  Return NULL if we can't find one.  */
-
-static varinfo_t
-first_vi_for_offset (varinfo_t start, unsigned HOST_WIDE_INT offset)
-{
-  /* If the offset is outside of the variable, bail out.  */
-  if (offset >= start->fullsize)
-    return NULL;
-
-  /* If we cannot reach offset from start, lookup the first field
-     and start from there.  */
-  if (start->offset > offset)
-    start = lookup_vi_for_tree (start->decl);
+  /* If we cannot reach offset from start, lookup the first field
+     and start from there.  */
+  if (start->offset > offset)
+    start = lookup_vi_for_tree (start->decl);
 
   while (start)
     {
 
   while (start)
     {
@@ -4839,6 +4075,47 @@ first_or_preceding_vi_for_offset (varinfo_t start,
 }
 
 
 }
 
 
+/* Insert the varinfo FIELD into the field list for BASE, at the front
+   of the list.  */
+
+static void
+insert_into_field_list (varinfo_t base, varinfo_t field)
+{
+  varinfo_t prev = base;
+  varinfo_t curr = base->next;
+
+  field->next = curr;
+  prev->next = field;
+}
+
+/* Insert the varinfo FIELD into the field list for BASE, ordered by
+   offset.  */
+
+static void
+insert_into_field_list_sorted (varinfo_t base, varinfo_t field)
+{
+  varinfo_t prev = base;
+  varinfo_t curr = base->next;
+
+  if (curr == NULL)
+    {
+      prev->next = field;
+      field->next = NULL;
+    }
+  else
+    {
+      while (curr)
+       {
+         if (field->offset <= curr->offset)
+           break;
+         prev = curr;
+         curr = curr->next;
+       }
+      field->next = prev->next;
+      prev->next = field;
+    }
+}
+
 /* This structure is used during pushing fields onto the fieldstack
    to track the offset of the field, since bitpos_of_field gives it
    relative to its immediate containing type, and we want it relative
 /* This structure is used during pushing fields onto the fieldstack
    to track the offset of the field, since bitpos_of_field gives it
    relative to its immediate containing type, and we want it relative
@@ -4924,38 +4201,37 @@ var_can_have_subvars (const_tree v)
 
    OFFSET is used to keep track of the offset in this entire
    structure, rather than just the immediately containing structure.
 
    OFFSET is used to keep track of the offset in this entire
    structure, rather than just the immediately containing structure.
-   Returns false if the caller is supposed to handle the field we
-   recursed for.  */
+   Returns the number of fields pushed.  */
 
 
-static bool
+static int
 push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
 push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
-                            HOST_WIDE_INT offset, bool must_have_pointers_p)
+                            HOST_WIDE_INT offset)
 {
   tree field;
 {
   tree field;
-  bool empty_p = true;
+  int count = 0;
 
   if (TREE_CODE (type) != RECORD_TYPE)
 
   if (TREE_CODE (type) != RECORD_TYPE)
-    return false;
+    return 0;
 
   /* If the vector of fields is growing too big, bail out early.
      Callers check for VEC_length <= MAX_FIELDS_FOR_FIELD_SENSITIVE, make
      sure this fails.  */
   if (VEC_length (fieldoff_s, *fieldstack) > MAX_FIELDS_FOR_FIELD_SENSITIVE)
 
   /* If the vector of fields is growing too big, bail out early.
      Callers check for VEC_length <= MAX_FIELDS_FOR_FIELD_SENSITIVE, make
      sure this fails.  */
   if (VEC_length (fieldoff_s, *fieldstack) > MAX_FIELDS_FOR_FIELD_SENSITIVE)
-    return false;
+    return 0;
 
   for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
     if (TREE_CODE (field) == FIELD_DECL)
       {
        bool push = false;
 
   for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
     if (TREE_CODE (field) == FIELD_DECL)
       {
        bool push = false;
+       int pushed = 0;
        HOST_WIDE_INT foff = bitpos_of_field (field);
 
        if (!var_can_have_subvars (field)
            || TREE_CODE (TREE_TYPE (field)) == QUAL_UNION_TYPE
            || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
          push = true;
        HOST_WIDE_INT foff = bitpos_of_field (field);
 
        if (!var_can_have_subvars (field)
            || TREE_CODE (TREE_TYPE (field)) == QUAL_UNION_TYPE
            || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
          push = true;
-       else if (!push_fields_onto_fieldstack
-                   (TREE_TYPE (field), fieldstack, offset + foff,
-                    must_have_pointers_p)
+       else if (!(pushed = push_fields_onto_fieldstack
+                  (TREE_TYPE (field), fieldstack, offset + foff))
                 && (DECL_SIZE (field)
                     && !integer_zerop (DECL_SIZE (field))))
          /* Empty structures may have actual size, like in C++.  So
                 && (DECL_SIZE (field)
                     && !integer_zerop (DECL_SIZE (field))))
          /* Empty structures may have actual size, like in C++.  So
@@ -4978,12 +4254,12 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
            /* If adjacent fields do not contain pointers merge them.  */
            if (pair
                && !pair->may_have_pointers
            /* If adjacent fields do not contain pointers merge them.  */
            if (pair
                && !pair->may_have_pointers
+               && !could_have_pointers (field)
                && !pair->has_unknown_size
                && !has_unknown_size
                && !pair->has_unknown_size
                && !has_unknown_size
-               && pair->offset + (HOST_WIDE_INT)pair->size == offset + foff
-               && !must_have_pointers_p
-               && !could_have_pointers (field))
+               && pair->offset + (HOST_WIDE_INT)pair->size == offset + foff)
              {
              {
+               pair = VEC_last (fieldoff_s, *fieldstack);
                pair->size += TREE_INT_CST_LOW (DECL_SIZE (field));
              }
            else
                pair->size += TREE_INT_CST_LOW (DECL_SIZE (field));
              }
            else
@@ -4995,19 +4271,19 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
                  pair->size = TREE_INT_CST_LOW (DECL_SIZE (field));
                else
                  pair->size = -1;
                  pair->size = TREE_INT_CST_LOW (DECL_SIZE (field));
                else
                  pair->size = -1;
-               pair->may_have_pointers
-                 = must_have_pointers_p || could_have_pointers (field);
+               pair->may_have_pointers = could_have_pointers (field);
                pair->only_restrict_pointers
                  = (!has_unknown_size
                     && POINTER_TYPE_P (TREE_TYPE (field))
                     && TYPE_RESTRICT (TREE_TYPE (field)));
                pair->only_restrict_pointers
                  = (!has_unknown_size
                     && POINTER_TYPE_P (TREE_TYPE (field))
                     && TYPE_RESTRICT (TREE_TYPE (field)));
+               count++;
              }
          }
              }
          }
-
-       empty_p = false;
+       else
+         count += pushed;
       }
 
       }
 
-  return !empty_p;
+  return count;
 }
 
 /* Count the number of arguments DECL has, and set IS_VARARGS to true
 }
 
 /* Count the number of arguments DECL has, and set IS_VARARGS to true
@@ -5037,122 +4313,38 @@ count_num_arguments (tree decl, bool *is_varargs)
 /* Creation function node for DECL, using NAME, and return the index
    of the variable we've created for the function.  */
 
 /* Creation function node for DECL, using NAME, and return the index
    of the variable we've created for the function.  */
 
-static varinfo_t
+static unsigned int
 create_function_info_for (tree decl, const char *name)
 {
 create_function_info_for (tree decl, const char *name)
 {
-  struct function *fn = DECL_STRUCT_FUNCTION (decl);
-  varinfo_t vi, prev_vi;
+  varinfo_t vi;
   tree arg;
   unsigned int i;
   bool is_varargs = false;
   tree arg;
   unsigned int i;
   bool is_varargs = false;
-  unsigned int num_args = count_num_arguments (decl, &is_varargs);
 
   /* Create the variable info.  */
 
   vi = new_var_info (decl, name);
   vi->offset = 0;
   vi->size = 1;
 
   /* Create the variable info.  */
 
   vi = new_var_info (decl, name);
   vi->offset = 0;
   vi->size = 1;
-  vi->fullsize = fi_parm_base + num_args;
-  vi->is_fn_info = 1;
-  vi->may_have_pointers = false;
-  if (is_varargs)
-    vi->fullsize = ~0;
+  vi->fullsize = count_num_arguments (decl, &is_varargs) + 1;
   insert_vi_for_tree (vi->decl, vi);
 
   insert_vi_for_tree (vi->decl, vi);
 
-  prev_vi = vi;
-
-  /* Create a variable for things the function clobbers and one for
-     things the function uses.  */
-    {
-      varinfo_t clobbervi, usevi;
-      const char *newname;
-      char *tempname;
-
-      asprintf (&tempname, "%s.clobber", name);
-      newname = ggc_strdup (tempname);
-      free (tempname);
-
-      clobbervi = new_var_info (NULL, newname);
-      clobbervi->offset = fi_clobbers;
-      clobbervi->size = 1;
-      clobbervi->fullsize = vi->fullsize;
-      clobbervi->is_full_var = true;
-      clobbervi->is_global_var = false;
-      gcc_assert (prev_vi->offset < clobbervi->offset);
-      prev_vi->next = clobbervi;
-      prev_vi = clobbervi;
-
-      asprintf (&tempname, "%s.use", name);
-      newname = ggc_strdup (tempname);
-      free (tempname);
-
-      usevi = new_var_info (NULL, newname);
-      usevi->offset = fi_uses;
-      usevi->size = 1;
-      usevi->fullsize = vi->fullsize;
-      usevi->is_full_var = true;
-      usevi->is_global_var = false;
-      gcc_assert (prev_vi->offset < usevi->offset);
-      prev_vi->next = usevi;
-      prev_vi = usevi;
-    }
+  stats.total_vars++;
 
 
-  /* And one for the static chain.  */
-  if (fn->static_chain_decl != NULL_TREE)
+  /* If it's varargs, we don't know how many arguments it has, so we
+     can't do much.  */
+  if (is_varargs)
     {
     {
-      varinfo_t chainvi;
-      const char *newname;
-      char *tempname;
-
-      asprintf (&tempname, "%s.chain", name);
-      newname = ggc_strdup (tempname);
-      free (tempname);
-
-      chainvi = new_var_info (fn->static_chain_decl, newname);
-      chainvi->offset = fi_static_chain;
-      chainvi->size = 1;
-      chainvi->fullsize = vi->fullsize;
-      chainvi->is_full_var = true;
-      chainvi->is_global_var = false;
-      gcc_assert (prev_vi->offset < chainvi->offset);
-      prev_vi->next = chainvi;
-      prev_vi = chainvi;
-      insert_vi_for_tree (fn->static_chain_decl, chainvi);
+      vi->fullsize = ~0;
+      vi->size = ~0;
+      vi->is_unknown_size_var = true;
+      return vi->id;
     }
 
     }
 
-  /* Create a variable for the return var.  */
-  if (DECL_RESULT (decl) != NULL
-      || !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
-    {
-      varinfo_t resultvi;
-      const char *newname;
-      char *tempname;
-      tree resultdecl = decl;
-
-      if (DECL_RESULT (decl))
-       resultdecl = DECL_RESULT (decl);
-
-      asprintf (&tempname, "%s.result", name);
-      newname = ggc_strdup (tempname);
-      free (tempname);
-
-      resultvi = new_var_info (resultdecl, newname);
-      resultvi->offset = fi_result;
-      resultvi->size = 1;
-      resultvi->fullsize = vi->fullsize;
-      resultvi->is_full_var = true;
-      if (DECL_RESULT (decl))
-       resultvi->may_have_pointers = could_have_pointers (DECL_RESULT (decl));
-      gcc_assert (prev_vi->offset < resultvi->offset);
-      prev_vi->next = resultvi;
-      prev_vi = resultvi;
-      if (DECL_RESULT (decl))
-       insert_vi_for_tree (DECL_RESULT (decl), resultvi);
-    }
+  arg = DECL_ARGUMENTS (decl);
 
   /* Set up variables for each argument.  */
 
   /* Set up variables for each argument.  */
-  arg = DECL_ARGUMENTS (decl);
-  for (i = 0; i < num_args; i++)
+  for (i = 1; i < vi->fullsize; i++)
     {
       varinfo_t argvi;
       const char *newname;
     {
       varinfo_t argvi;
       const char *newname;
@@ -5162,20 +4354,17 @@ create_function_info_for (tree decl, const char *name)
       if (arg)
        argdecl = arg;
 
       if (arg)
        argdecl = arg;
 
-      asprintf (&tempname, "%s.arg%d", name, i);
+      asprintf (&tempname, "%s.arg%d", name, i-1);
       newname = ggc_strdup (tempname);
       free (tempname);
 
       argvi = new_var_info (argdecl, newname);
       newname = ggc_strdup (tempname);
       free (tempname);
 
       argvi = new_var_info (argdecl, newname);
-      argvi->offset = fi_parm_base + i;
+      argvi->offset = i;
       argvi->size = 1;
       argvi->is_full_var = true;
       argvi->fullsize = vi->fullsize;
       argvi->size = 1;
       argvi->is_full_var = true;
       argvi->fullsize = vi->fullsize;
-      if (arg)
-       argvi->may_have_pointers = could_have_pointers (arg);
-      gcc_assert (prev_vi->offset < argvi->offset);
-      prev_vi->next = argvi;
-      prev_vi = argvi;
+      insert_into_field_list_sorted (vi, argvi);
+      stats.total_vars ++;
       if (arg)
        {
          insert_vi_for_tree (arg, argvi);
       if (arg)
        {
          insert_vi_for_tree (arg, argvi);
@@ -5183,34 +4372,36 @@ create_function_info_for (tree decl, const char *name)
        }
     }
 
        }
     }
 
-  /* Add one representative for all further args.  */
-  if (is_varargs)
+  /* Create a variable for the return var.  */
+  if (DECL_RESULT (decl) != NULL
+      || !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
     {
     {
-      varinfo_t argvi;
+      varinfo_t resultvi;
       const char *newname;
       char *tempname;
       const char *newname;
       char *tempname;
-      tree decl;
+      tree resultdecl = decl;
+
+      vi->fullsize ++;
 
 
-      asprintf (&tempname, "%s.varargs", name);
+      if (DECL_RESULT (decl))
+       resultdecl = DECL_RESULT (decl);
+
+      asprintf (&tempname, "%s.result", name);
       newname = ggc_strdup (tempname);
       free (tempname);
 
       newname = ggc_strdup (tempname);
       free (tempname);
 
-      /* We need sth that can be pointed to for va_start.  */
-      decl = create_tmp_var_raw (ptr_type_node, name);
-      get_var_ann (decl);
-
-      argvi = new_var_info (decl, newname);
-      argvi->offset = fi_parm_base + num_args;
-      argvi->size = ~0;
-      argvi->is_full_var = true;
-      argvi->is_heap_var = true;
-      argvi->fullsize = vi->fullsize;
-      gcc_assert (prev_vi->offset < argvi->offset);
-      prev_vi->next = argvi;
-      prev_vi = argvi;
+      resultvi = new_var_info (resultdecl, newname);
+      resultvi->offset = i;
+      resultvi->size = 1;
+      resultvi->fullsize = vi->fullsize;
+      resultvi->is_full_var = true;
+      insert_into_field_list_sorted (vi, resultvi);
+      stats.total_vars ++;
+      if (DECL_RESULT (decl))
+       insert_vi_for_tree (DECL_RESULT (decl), resultvi);
     }
 
     }
 
-  return vi;
+  return vi->id;
 }
 
 
 }
 
 
@@ -5237,54 +4428,67 @@ check_for_overlaps (VEC (fieldoff_s,heap) *fieldstack)
    This will also create any varinfo structures necessary for fields
    of DECL.  */
 
    This will also create any varinfo structures necessary for fields
    of DECL.  */
 
-static varinfo_t
-create_variable_info_for_1 (tree decl, const char *name)
+static unsigned int
+create_variable_info_for (tree decl, const char *name)
 {
 {
-  varinfo_t vi, newvi;
+  varinfo_t vi;
   tree decl_type = TREE_TYPE (decl);
   tree declsize = DECL_P (decl) ? DECL_SIZE (decl) : TYPE_SIZE (decl_type);
   VEC (fieldoff_s,heap) *fieldstack = NULL;
   tree decl_type = TREE_TYPE (decl);
   tree declsize = DECL_P (decl) ? DECL_SIZE (decl) : TYPE_SIZE (decl_type);
   VEC (fieldoff_s,heap) *fieldstack = NULL;
-  fieldoff_s *fo;
-  unsigned int i;
 
 
+  if (var_can_have_subvars (decl) && use_field_sensitive)
+    push_fields_onto_fieldstack (decl_type, &fieldstack, 0);
+
+  /* If the variable doesn't have subvars, we may end up needing to
+     sort the field list and create fake variables for all the
+     fields.  */
+  vi = new_var_info (decl, name);
+  vi->offset = 0;
+  vi->may_have_pointers = could_have_pointers (decl);
   if (!declsize
       || !host_integerp (declsize, 1))
     {
   if (!declsize
       || !host_integerp (declsize, 1))
     {
-      vi = new_var_info (decl, name);
-      vi->offset = 0;
-      vi->size = ~0;
-      vi->fullsize = ~0;
       vi->is_unknown_size_var = true;
       vi->is_unknown_size_var = true;
-      vi->is_full_var = true;
-      vi->may_have_pointers = could_have_pointers (decl);
-      return vi;
+      vi->fullsize = ~0;
+      vi->size = ~0;
+    }
+  else
+    {
+      vi->fullsize = TREE_INT_CST_LOW (declsize);
+      vi->size = vi->fullsize;
+    }
+
+  insert_vi_for_tree (vi->decl, vi);
+  if (vi->is_global_var
+      && (!flag_whole_program || !in_ipa_mode)
+      && vi->may_have_pointers)
+    {
+      if (POINTER_TYPE_P (TREE_TYPE (decl))
+         && TYPE_RESTRICT (TREE_TYPE (decl)))
+       make_constraint_from_restrict (vi, "GLOBAL_RESTRICT");
+      make_copy_constraint (vi, nonlocal_id);
     }
 
     }
 
-  /* Collect field information.  */
+  stats.total_vars++;
   if (use_field_sensitive
   if (use_field_sensitive
+      && !vi->is_unknown_size_var
       && var_can_have_subvars (decl)
       && var_can_have_subvars (decl)
-      /* ???  Force us to not use subfields for global initializers
-        in IPA mode.  Else we'd have to parse arbitrary initializers.  */
-      && !(in_ipa_mode
-          && is_global_var (decl)
-          && DECL_INITIAL (decl)))
+      && VEC_length (fieldoff_s, fieldstack) > 1
+      && VEC_length (fieldoff_s, fieldstack) <= MAX_FIELDS_FOR_FIELD_SENSITIVE)
     {
       fieldoff_s *fo = NULL;
       bool notokay = false;
       unsigned int i;
 
     {
       fieldoff_s *fo = NULL;
       bool notokay = false;
       unsigned int i;
 
-      push_fields_onto_fieldstack (decl_type, &fieldstack, 0,
-                                  TREE_PUBLIC (decl)
-                                  || DECL_EXTERNAL (decl)
-                                  || TREE_ADDRESSABLE (decl));
-
       for (i = 0; !notokay && VEC_iterate (fieldoff_s, fieldstack, i, fo); i++)
       for (i = 0; !notokay && VEC_iterate (fieldoff_s, fieldstack, i, fo); i++)
-       if (fo->has_unknown_size
-           || fo->offset < 0)
-         {
-           notokay = true;
-           break;
-         }
+       {
+         if (fo->has_unknown_size
+             || fo->offset < 0)
+           {
+             notokay = true;
+             break;
+           }
+       }
 
       /* We can't sort them if we have a field with a variable sized type,
         which will make notokay = true.  In that case, we are going to return
 
       /* We can't sort them if we have a field with a variable sized type,
         which will make notokay = true.  In that case, we are going to return
@@ -5300,112 +4504,70 @@ create_variable_info_for_1 (tree decl, const char *name)
          notokay = check_for_overlaps (fieldstack);
        }
 
          notokay = check_for_overlaps (fieldstack);
        }
 
-      if (notokay)
-       VEC_free (fieldoff_s, heap, fieldstack);
-    }
 
 
-  /* If we didn't end up collecting sub-variables create a full
-     variable for the decl.  */
-  if (VEC_length (fieldoff_s, fieldstack) <= 1
-      || VEC_length (fieldoff_s, fieldstack) > MAX_FIELDS_FOR_FIELD_SENSITIVE)
-    {
-      vi = new_var_info (decl, name);
-      vi->offset = 0;
-      vi->may_have_pointers = could_have_pointers (decl);
-      vi->fullsize = TREE_INT_CST_LOW (declsize);
-      vi->size = vi->fullsize;
-      vi->is_full_var = true;
-      VEC_free (fieldoff_s, heap, fieldstack);
-      return vi;
-    }
+      if (VEC_length (fieldoff_s, fieldstack) != 0)
+       fo = VEC_index (fieldoff_s, fieldstack, 0);
 
 
-  vi = new_var_info (decl, name);
-  vi->fullsize = TREE_INT_CST_LOW (declsize);
-  for (i = 0, newvi = vi;
-       VEC_iterate (fieldoff_s, fieldstack, i, fo);
-       ++i, newvi = newvi->next)
-    {
-      const char *newname = "NULL";
-      char *tempname;
-
-      if (dump_file)
+      if (fo == NULL || notokay)
        {
        {
-         asprintf (&tempname, "%s." HOST_WIDE_INT_PRINT_DEC
-                   "+" HOST_WIDE_INT_PRINT_DEC, name, fo->offset, fo->size);
-         newname = ggc_strdup (tempname);
-         free (tempname);
+         vi->is_unknown_size_var = 1;
+         vi->fullsize = ~0;
+         vi->size = ~0;
+         vi->is_full_var = true;
+         VEC_free (fieldoff_s, heap, fieldstack);
+         return vi->id;
        }
        }
-      newvi->name = newname;
-      newvi->offset = fo->offset;
-      newvi->size = fo->size;
-      newvi->fullsize = vi->fullsize;
-      newvi->may_have_pointers = fo->may_have_pointers;
-      newvi->only_restrict_pointers = fo->only_restrict_pointers;
-      if (i + 1 < VEC_length (fieldoff_s, fieldstack))
-       newvi->next = new_var_info (decl, name);
-    }
 
 
-  VEC_free (fieldoff_s, heap, fieldstack);
-
-  return vi;
-}
-
-static unsigned int
-create_variable_info_for (tree decl, const char *name)
-{
-  varinfo_t vi = create_variable_info_for_1 (decl, name);
-  unsigned int id = vi->id;
-
-  insert_vi_for_tree (decl, vi);
-
-  /* Create initial constraints for globals.  */
-  for (; vi; vi = vi->next)
-    {
-      if (!vi->may_have_pointers
-         || !vi->is_global_var)
-       continue;
-
-      /* Mark global restrict qualified pointers.  */
-      if ((POINTER_TYPE_P (TREE_TYPE (decl))
-          && TYPE_RESTRICT (TREE_TYPE (decl)))
-         || vi->only_restrict_pointers)
-       make_constraint_from_restrict (vi, "GLOBAL_RESTRICT");
-
-      /* For escaped variables initialize them from nonlocal.  */
-      if (!in_ipa_mode
-         || DECL_EXTERNAL (decl) || TREE_PUBLIC (decl))
-       make_copy_constraint (vi, nonlocal_id);
-
-      /* If this is a global variable with an initializer and we are in
-        IPA mode generate constraints for it.  In non-IPA mode
-        the initializer from nonlocal is all we need.  */
-      if (in_ipa_mode
-         && DECL_INITIAL (decl))
+      vi->size = fo->size;
+      vi->offset = fo->offset;
+      vi->may_have_pointers = fo->may_have_pointers;
+      if (vi->is_global_var
+         && (!flag_whole_program || !in_ipa_mode)
+         && vi->may_have_pointers)
        {
        {
-         VEC (ce_s, heap) *rhsc = NULL;
-         struct constraint_expr lhs, *rhsp;
-         unsigned i;
-         get_constraint_for (DECL_INITIAL (decl), &rhsc);
-         lhs.var = vi->id;
-         lhs.offset = 0;
-         lhs.type = SCALAR;
-         for (i = 0; VEC_iterate (ce_s, rhsc, i, rhsp); ++i)
-           process_constraint (new_constraint (lhs, *rhsp));
-         /* If this is a variable that escapes from the unit
-            the initializer escapes as well.  */
-         if (DECL_EXTERNAL (decl) || TREE_PUBLIC (decl))
+         if (fo->only_restrict_pointers)
+           make_constraint_from_restrict (vi, "GLOBAL_RESTRICT");
+       }
+      for (i = VEC_length (fieldoff_s, fieldstack) - 1;
+          i >= 1 && VEC_iterate (fieldoff_s, fieldstack, i, fo);
+          i--)
+       {
+         varinfo_t newvi;
+         const char *newname = "NULL";
+         char *tempname;
+
+         if (dump_file)
            {
            {
-             lhs.var = escaped_id;
-             lhs.offset = 0;
-             lhs.type = SCALAR;
-             for (i = 0; VEC_iterate (ce_s, rhsc, i, rhsp); ++i)
-               process_constraint (new_constraint (lhs, *rhsp));
+             asprintf (&tempname, "%s." HOST_WIDE_INT_PRINT_DEC
+                       "+" HOST_WIDE_INT_PRINT_DEC,
+                       vi->name, fo->offset, fo->size);
+             newname = ggc_strdup (tempname);
+             free (tempname);
            }
            }
-         VEC_free (ce_s, heap, rhsc);
+         newvi = new_var_info (decl, newname);
+         newvi->offset = fo->offset;
+         newvi->size = fo->size;
+         newvi->fullsize = vi->fullsize;
+         newvi->may_have_pointers = fo->may_have_pointers;
+         insert_into_field_list (vi, newvi);
+         if ((newvi->is_global_var || TREE_CODE (decl) == PARM_DECL)
+             && newvi->may_have_pointers)
+           {
+              if (fo->only_restrict_pointers)
+                make_constraint_from_restrict (newvi, "GLOBAL_RESTRICT");
+              if (newvi->is_global_var && !in_ipa_mode)
+                make_copy_constraint (newvi, nonlocal_id);
+           }
+
+         stats.total_vars++;
        }
     }
        }
     }
+  else
+    vi->is_full_var = true;
+
+  VEC_free (fieldoff_s, heap, fieldstack);
 
 
-  return id;
+  return vi->id;
 }
 
 /* Print out the points-to solution for VAR to FILE.  */
 }
 
 /* Print out the points-to solution for VAR to FILE.  */
@@ -5417,19 +4579,20 @@ dump_solution_for_var (FILE *file, unsigned int var)
   unsigned int i;
   bitmap_iterator bi;
 
   unsigned int i;
   bitmap_iterator bi;
 
-  /* Dump the solution for unified vars anyway, this avoids difficulties
-     in scanning dumps in the testsuite.  */
-  fprintf (file, "%s = { ", vi->name);
-  vi = get_varinfo (find (var));
-  EXECUTE_IF_SET_IN_BITMAP (vi->solution, 0, i, bi)
-    fprintf (file, "%s ", get_varinfo (i)->name);
-  fprintf (file, "}");
-
-  /* But note when the variable was unified.  */
-  if (vi->id != var)
-    fprintf (file, " same as %s", vi->name);
-
-  fprintf (file, "\n");
+  if (find (var) != var)
+    {
+      varinfo_t vipt = get_varinfo (find (var));
+      fprintf (file, "%s = same as %s\n", vi->name, vipt->name);
+    }
+  else
+    {
+      fprintf (file, "%s = { ", vi->name);
+      EXECUTE_IF_SET_IN_BITMAP (vi->solution, 0, i, bi)
+       {
+         fprintf (file, "%s ", get_varinfo (i)->name);
+       }
+      fprintf (file, "}\n");
+    }
 }
 
 /* Print the points-to solution for VAR to stdout.  */
 }
 
 /* Print the points-to solution for VAR to stdout.  */
@@ -5491,12 +4654,8 @@ intra_create_variable_infos (void)
        }
 
       for (p = get_vi_for_tree (t); p; p = p->next)
        }
 
       for (p = get_vi_for_tree (t); p; p = p->next)
-       {
-         if (p->may_have_pointers)
-           make_constraint_from (p, nonlocal_id);
-         if (p->only_restrict_pointers)
-           make_constraint_from_restrict (p, "PARM_RESTRICT");
-       }
+       if (p->may_have_pointers)
+         make_constraint_from (p, nonlocal_id);
       if (POINTER_TYPE_P (TREE_TYPE (t))
          && TYPE_RESTRICT (TREE_TYPE (t)))
        make_constraint_from_restrict (get_vi_for_tree (t), "PARM_RESTRICT");
       if (POINTER_TYPE_P (TREE_TYPE (t))
          && TYPE_RESTRICT (TREE_TYPE (t)))
        make_constraint_from_restrict (get_vi_for_tree (t), "PARM_RESTRICT");
@@ -5613,15 +4772,9 @@ set_uids_in_ptset (bitmap into, bitmap from, struct pt_solution *pt)
          || TREE_CODE (vi->decl) == PARM_DECL
          || TREE_CODE (vi->decl) == RESULT_DECL)
        {
          || TREE_CODE (vi->decl) == PARM_DECL
          || TREE_CODE (vi->decl) == RESULT_DECL)
        {
-         /* If we are in IPA mode we will not recompute points-to
-            sets after inlining so make sure they stay valid.  */
-         if (in_ipa_mode
-             && !DECL_PT_UID_SET_P (vi->decl))
-           SET_DECL_PT_UID (vi->decl, DECL_UID (vi->decl));
-
          /* Add the decl to the points-to set.  Note that the points-to
             set contains global variables.  */
          /* Add the decl to the points-to set.  Note that the points-to
             set contains global variables.  */
-         bitmap_set_bit (into, DECL_PT_UID (vi->decl));
+         bitmap_set_bit (into, DECL_UID (vi->decl));
          if (vi->is_global_var)
            pt->vars_contains_global = true;
        }
          if (vi->is_global_var)
            pt->vars_contains_global = true;
        }
@@ -5657,12 +4810,9 @@ find_what_var_points_to (varinfo_t orig_vi, struct pt_solution *pt)
          if (vi->id == nothing_id)
            pt->null = 1;
          else if (vi->id == escaped_id)
          if (vi->id == nothing_id)
            pt->null = 1;
          else if (vi->id == escaped_id)
-           {
-             if (in_ipa_mode)
-               pt->ipa_escaped = 1;
-             else
-               pt->escaped = 1;
-           }
+           pt->escaped = 1;
+         else if (vi->id == callused_id)
+           gcc_unreachable ();
          else if (vi->id == nonlocal_id)
            pt->nonlocal = 1;
          else if (vi->is_heap_var)
          else if (vi->id == nonlocal_id)
            pt->nonlocal = 1;
          else if (vi->is_heap_var)
@@ -5768,53 +4918,30 @@ pt_solution_reset (struct pt_solution *pt)
 }
 
 /* Set the points-to solution *PT to point only to the variables
 }
 
 /* Set the points-to solution *PT to point only to the variables
-   in VARS.  VARS_CONTAINS_GLOBAL specifies whether that contains
-   global variables and VARS_CONTAINS_RESTRICT specifies whether
-   it contains restrict tag variables.  */
+   in VARS.  */
 
 void
 
 void
-pt_solution_set (struct pt_solution *pt, bitmap vars,
-                bool vars_contains_global, bool vars_contains_restrict)
+pt_solution_set (struct pt_solution *pt, bitmap vars)
 {
 {
+  bitmap_iterator bi;
+  unsigned i;
+
   memset (pt, 0, sizeof (struct pt_solution));
   pt->vars = vars;
   memset (pt, 0, sizeof (struct pt_solution));
   pt->vars = vars;
-  pt->vars_contains_global = vars_contains_global;
-  pt->vars_contains_restrict = vars_contains_restrict;
-}
-
-/* Computes the union of the points-to solutions *DEST and *SRC and
-   stores the result in *DEST.  This changes the points-to bitmap
-   of *DEST and thus may not be used if that might be shared.
-   The points-to bitmap of *SRC and *DEST will not be shared after
-   this function if they were not before.  */
-
-static void
-pt_solution_ior_into (struct pt_solution *dest, struct pt_solution *src)
-{
-  dest->anything |= src->anything;
-  if (dest->anything)
+  EXECUTE_IF_SET_IN_BITMAP (vars, 0, i, bi)
     {
     {
-      pt_solution_reset (dest);
-      return;
+      tree var = referenced_var_lookup (i);
+      if (is_global_var (var))
+       {
+         pt->vars_contains_global = true;
+         break;
+       }
     }
     }
-
-  dest->nonlocal |= src->nonlocal;
-  dest->escaped |= src->escaped;
-  dest->ipa_escaped |= src->ipa_escaped;
-  dest->null |= src->null;
-  dest->vars_contains_global |= src->vars_contains_global;
-  dest->vars_contains_restrict |= src->vars_contains_restrict;
-  if (!src->vars)
-    return;
-
-  if (!dest->vars)
-    dest->vars = BITMAP_GGC_ALLOC ();
-  bitmap_ior_into (dest->vars, src->vars);
 }
 
 /* Return true if the points-to solution *PT is empty.  */
 
 }
 
 /* Return true if the points-to solution *PT is empty.  */
 
-bool
+static bool
 pt_solution_empty_p (struct pt_solution *pt)
 {
   if (pt->anything
 pt_solution_empty_p (struct pt_solution *pt)
 {
   if (pt->anything
@@ -5830,11 +4957,6 @@ pt_solution_empty_p (struct pt_solution *pt)
       && !pt_solution_empty_p (&cfun->gimple_df->escaped))
     return false;
 
       && !pt_solution_empty_p (&cfun->gimple_df->escaped))
     return false;
 
-  /* If the solution includes ESCAPED, check if that is empty.  */
-  if (pt->ipa_escaped
-      && !pt_solution_empty_p (&ipa_escaped_pt))
-    return false;
-
   return true;
 }
 
   return true;
 }
 
@@ -5851,15 +4973,6 @@ pt_solution_includes_global (struct pt_solution *pt)
   if (pt->escaped)
     return pt_solution_includes_global (&cfun->gimple_df->escaped);
 
   if (pt->escaped)
     return pt_solution_includes_global (&cfun->gimple_df->escaped);
 
-  if (pt->ipa_escaped)
-    return pt_solution_includes_global (&ipa_escaped_pt);
-
-  /* ???  This predicate is not correct for the IPA-PTA solution
-     as we do not properly distinguish between unit escape points
-     and global variables.  */
-  if (cfun->gimple_df->ipa_pta)
-    return true;
-
   return false;
 }
 
   return false;
 }
 
@@ -5877,7 +4990,7 @@ pt_solution_includes_1 (struct pt_solution *pt, const_tree decl)
     return true;
 
   if (pt->vars
     return true;
 
   if (pt->vars
-      && bitmap_bit_p (pt->vars, DECL_PT_UID (decl)))
+      && bitmap_bit_p (pt->vars, DECL_UID (decl)))
     return true;
 
   /* If the solution includes ESCAPED, check it.  */
     return true;
 
   /* If the solution includes ESCAPED, check it.  */
@@ -5885,11 +4998,6 @@ pt_solution_includes_1 (struct pt_solution *pt, const_tree decl)
       && pt_solution_includes_1 (&cfun->gimple_df->escaped, decl))
     return true;
 
       && pt_solution_includes_1 (&cfun->gimple_df->escaped, decl))
     return true;
 
-  /* If the solution includes ESCAPED, check it.  */
-  if (pt->ipa_escaped
-      && pt_solution_includes_1 (&ipa_escaped_pt, decl))
-    return true;
-
   return false;
 }
 
   return false;
 }
 
@@ -5940,25 +5048,6 @@ pt_solutions_intersect_1 (struct pt_solution *pt1, struct pt_solution *pt2)
        return true;
     }
 
        return true;
     }
 
-  /* Check the escaped solution if required.
-     ???  Do we need to check the local against the IPA escaped sets?  */
-  if ((pt1->ipa_escaped || pt2->ipa_escaped)
-      && !pt_solution_empty_p (&ipa_escaped_pt))
-    {
-      /* If both point to escaped memory and that solution
-        is not empty they alias.  */
-      if (pt1->ipa_escaped && pt2->ipa_escaped)
-       return true;
-
-      /* If either points to escaped memory see if the escaped solution
-        intersects with the other.  */
-      if ((pt1->ipa_escaped
-          && pt_solutions_intersect_1 (&ipa_escaped_pt, pt2))
-         || (pt2->ipa_escaped
-             && pt_solutions_intersect_1 (&ipa_escaped_pt, pt1)))
-       return true;
-    }
-
   /* Now both pointers alias if their points-to solution intersects.  */
   return (pt1->vars
          && pt2->vars
   /* Now both pointers alias if their points-to solution intersects.  */
   return (pt1->vars
          && pt2->vars
@@ -6024,12 +5113,7 @@ dump_sa_points_to_info (FILE *outfile)
     }
 
   for (i = 0; i < VEC_length (varinfo_t, varmap); i++)
     }
 
   for (i = 0; i < VEC_length (varinfo_t, varmap); i++)
-    {
-      varinfo_t vi = get_varinfo (i);
-      if (!vi->may_have_pointers)
-       continue;
-      dump_solution_for_var (outfile, i);
-    }
+    dump_solution_for_var (outfile, i);
 }
 
 
 }
 
 
@@ -6054,6 +5138,7 @@ init_base_vars (void)
   varinfo_t var_readonly;
   varinfo_t var_escaped;
   varinfo_t var_nonlocal;
   varinfo_t var_readonly;
   varinfo_t var_escaped;
   varinfo_t var_nonlocal;
+  varinfo_t var_callused;
   varinfo_t var_storedanything;
   varinfo_t var_integer;
 
   varinfo_t var_storedanything;
   varinfo_t var_integer;
 
@@ -6066,8 +5151,6 @@ init_base_vars (void)
   var_nothing->size = ~0;
   var_nothing->fullsize = ~0;
   var_nothing->is_special_var = 1;
   var_nothing->size = ~0;
   var_nothing->fullsize = ~0;
   var_nothing->is_special_var = 1;
-  var_nothing->may_have_pointers = 0;
-  var_nothing->is_global_var = 0;
 
   /* Create the ANYTHING variable, used to represent that a variable
      points to some unknown piece of memory.  */
 
   /* Create the ANYTHING variable, used to represent that a variable
      points to some unknown piece of memory.  */
@@ -6182,6 +5265,35 @@ init_base_vars (void)
   rhs.offset = 0;
   process_constraint (new_constraint (lhs, rhs));
 
   rhs.offset = 0;
   process_constraint (new_constraint (lhs, rhs));
 
+  /* Create the CALLUSED variable, used to represent the set of call-used
+     memory.  */
+  var_callused = new_var_info (NULL_TREE, "CALLUSED");
+  gcc_assert (var_callused->id == callused_id);
+  var_callused->is_artificial_var = 1;
+  var_callused->offset = 0;
+  var_callused->size = ~0;
+  var_callused->fullsize = ~0;
+  var_callused->is_special_var = 0;
+
+  /* CALLUSED = *CALLUSED, because call-used is may-deref'd at calls, etc.  */
+  lhs.type = SCALAR;
+  lhs.var = callused_id;
+  lhs.offset = 0;
+  rhs.type = DEREF;
+  rhs.var = callused_id;
+  rhs.offset = 0;
+  process_constraint (new_constraint (lhs, rhs));
+
+  /* CALLUSED = CALLUSED + UNKNOWN, because if a sub-field is call-used the
+     whole variable is call-used.  */
+  lhs.type = SCALAR;
+  lhs.var = callused_id;
+  lhs.offset = 0;
+  rhs.type = SCALAR;
+  rhs.var = callused_id;
+  rhs.offset = UNKNOWN_OFFSET;
+  process_constraint (new_constraint (lhs, rhs));
+
   /* Create the STOREDANYTHING variable, used to represent the set of
      variables stored to *ANYTHING.  */
   var_storedanything = new_var_info (NULL_TREE, "STOREDANYTHING");
   /* Create the STOREDANYTHING variable, used to represent the set of
      variables stored to *ANYTHING.  */
   var_storedanything = new_var_info (NULL_TREE, "STOREDANYTHING");
@@ -6232,7 +5344,6 @@ init_alias_vars (void)
   constraints = VEC_alloc (constraint_t, heap, 8);
   varmap = VEC_alloc (varinfo_t, heap, 8);
   vi_for_tree = pointer_map_create ();
   constraints = VEC_alloc (constraint_t, heap, 8);
   varmap = VEC_alloc (varinfo_t, heap, 8);
   vi_for_tree = pointer_map_create ();
-  call_stmt_vars = pointer_map_create ();
 
   memset (&stats, 0, sizeof (stats));
   shared_bitmap_table = htab_create (511, shared_bitmap_hash,
 
   memset (&stats, 0, sizeof (stats));
   shared_bitmap_table = htab_create (511, shared_bitmap_hash,
@@ -6304,6 +5415,12 @@ solve_constraints (void)
   struct scc_info *si;
 
   if (dump_file)
   struct scc_info *si;
 
   if (dump_file)
+    {
+      fprintf (dump_file, "Points-to analysis\n\nConstraints:\n\n");
+      dump_constraints (dump_file);
+    }
+
+  if (dump_file)
     fprintf (dump_file,
             "\nCollapsing static cycles and doing variable "
             "substitution\n");
     fprintf (dump_file,
             "\nCollapsing static cycles and doing variable "
             "substitution\n");
@@ -6363,6 +5480,7 @@ compute_points_to_sets (void)
   basic_block bb;
   unsigned i;
   varinfo_t vi;
   basic_block bb;
   unsigned i;
   varinfo_t vi;
+  struct pt_solution callused;
 
   timevar_push (TV_TREE_PTA);
 
 
   timevar_push (TV_TREE_PTA);
 
@@ -6371,7 +5489,7 @@ compute_points_to_sets (void)
 
   intra_create_variable_infos ();
 
 
   intra_create_variable_infos ();
 
-  /* Now walk all statements and build the constraint set.  */
+  /* Now walk all statements and derive aliases.  */
   FOR_EACH_BB (bb)
     {
       gimple_stmt_iterator gsi;
   FOR_EACH_BB (bb)
     {
       gimple_stmt_iterator gsi;
@@ -6392,18 +5510,14 @@ compute_points_to_sets (void)
        }
     }
 
        }
     }
 
-  if (dump_file)
-    {
-      fprintf (dump_file, "Points-to analysis\n\nConstraints:\n\n");
-      dump_constraints (dump_file, 0);
-    }
-
   /* From the constraints compute the points-to sets.  */
   solve_constraints ();
 
   /* From the constraints compute the points-to sets.  */
   solve_constraints ();
 
-  /* Compute the points-to set for ESCAPED used for call-clobber analysis.  */
+  /* Compute the points-to sets for ESCAPED and CALLUSED used for
+     call-clobber analysis.  */
   find_what_var_points_to (get_varinfo (escaped_id),
                           &cfun->gimple_df->escaped);
   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
 
   /* Make sure the ESCAPED solution (which is used as placeholder in
      other solutions) does not reference itself.  This simplifies
@@ -6442,11 +5556,11 @@ compute_points_to_sets (void)
          pt = gimple_call_use_set (stmt);
          if (gimple_call_flags (stmt) & ECF_CONST)
            memset (pt, 0, sizeof (struct pt_solution));
          pt = gimple_call_use_set (stmt);
          if (gimple_call_flags (stmt) & ECF_CONST)
            memset (pt, 0, sizeof (struct pt_solution));
-         else if ((vi = lookup_call_use_vi (stmt)) != NULL)
+         else if (gimple_call_flags (stmt) & ECF_PURE)
            {
            {
-             find_what_var_points_to (vi, pt);
-             /* Escaped (and thus nonlocal) variables are always
-                implicitly used by calls.  */
+             /* 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;
              /* ???  ESCAPED can be empty even though NONLOCAL
                 always escaped.  */
              pt->nonlocal = 1;
@@ -6454,8 +5568,6 @@ compute_points_to_sets (void)
            }
          else
            {
            }
          else
            {
-             /* If there is nothing special about this call then
-                we have made everything that is used also escape.  */
              *pt = cfun->gimple_df->escaped;
              pt->nonlocal = 1;
            }
              *pt = cfun->gimple_df->escaped;
              pt->nonlocal = 1;
            }
@@ -6463,20 +5575,8 @@ compute_points_to_sets (void)
          pt = gimple_call_clobber_set (stmt);
          if (gimple_call_flags (stmt) & (ECF_CONST|ECF_PURE|ECF_NOVOPS))
            memset (pt, 0, sizeof (struct pt_solution));
          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 if ((vi = lookup_call_clobber_vi (stmt)) != NULL)
-           {
-             find_what_var_points_to (vi, pt);
-             /* Escaped (and thus nonlocal) variables are always
-                implicitly clobbered by calls.  */
-             /* ???  ESCAPED can be empty even though NONLOCAL
-                always escaped.  */
-             pt->nonlocal = 1;
-             pt->escaped = 1;
-           }
          else
            {
          else
            {
-             /* If there is nothing special about this call then
-                we have made everything that is used also escape.  */
              *pt = cfun->gimple_df->escaped;
              pt->nonlocal = 1;
            }
              *pt = cfun->gimple_df->escaped;
              pt->nonlocal = 1;
            }
@@ -6500,7 +5600,6 @@ delete_points_to_sets (void)
             stats.points_to_sets_created);
 
   pointer_map_destroy (vi_for_tree);
             stats.points_to_sets_created);
 
   pointer_map_destroy (vi_for_tree);
-  pointer_map_destroy (call_stmt_vars);
   bitmap_obstack_release (&pta_obstack);
   VEC_free (constraint_t, heap, constraints);
 
   bitmap_obstack_release (&pta_obstack);
   VEC_free (constraint_t, heap, constraints);
 
@@ -6528,23 +5627,6 @@ delete_points_to_sets (void)
 unsigned int
 compute_may_aliases (void)
 {
 unsigned int
 compute_may_aliases (void)
 {
-  if (cfun->gimple_df->ipa_pta)
-    {
-      if (dump_file)
-       {
-         fprintf (dump_file, "\nNot re-computing points-to information "
-                  "because IPA points-to information is available.\n\n");
-
-         /* But still dump what we have remaining it.  */
-         dump_alias_info (dump_file);
-
-         if (dump_flags & TDF_DETAILS)
-           dump_referenced_vars (dump_file);
-       }
-
-      return 0;
-    }
-
   /* For each pointer P_i, determine the sets of variables that P_i may
      point-to.  Compute the reachability set of escaped and call-used
      variables.  */
   /* For each pointer P_i, determine the sets of variables that P_i may
      point-to.  Compute the reachability set of escaped and call-used
      variables.  */
@@ -6629,17 +5711,11 @@ gate_ipa_pta (void)
          && !(errorcount || sorrycount));
 }
 
          && !(errorcount || sorrycount));
 }
 
-/* IPA PTA solutions for ESCAPED.  */
-struct pt_solution ipa_escaped_pt
-  = { true, false, false, false, false, false, false, NULL };
-
 /* Execute the driver for IPA PTA.  */
 static unsigned int
 ipa_pta_execute (void)
 {
   struct cgraph_node *node;
 /* Execute the driver for IPA PTA.  */
 static unsigned int
 ipa_pta_execute (void)
 {
   struct cgraph_node *node;
-  struct varpool_node *var;
-  int from;
 
   in_ipa_mode = 1;
 
 
   in_ipa_mode = 1;
 
@@ -6649,9 +5725,6 @@ ipa_pta_execute (void)
   /* Build the constraints.  */
   for (node = cgraph_nodes; node; node = node->next)
     {
   /* Build the constraints.  */
   for (node = cgraph_nodes; node; node = node->next)
     {
-      struct cgraph_node *alias;
-      varinfo_t vi;
-
       /* Nodes without a body are not interesting.  Especially do not
          visit clones at this point for now - we get duplicate decls
         there for inline clones at least.  */
       /* Nodes without a body are not interesting.  Especially do not
          visit clones at this point for now - we get duplicate decls
         there for inline clones at least.  */
@@ -6659,35 +5732,15 @@ ipa_pta_execute (void)
          || node->clone_of)
        continue;
 
          || node->clone_of)
        continue;
 
-      vi = create_function_info_for (node->decl,
-                                    alias_get_name (node->decl));
-
-      /* Associate the varinfo node with all aliases.  */
-      for (alias = node->same_body; alias; alias = alias->next)
-       insert_vi_for_tree (alias->decl, vi);
-    }
-
-  /* Create constraints for global variables and their initializers.  */
-  for (var = varpool_nodes; var; var = var->next)
-    {
-      struct varpool_node *alias;
-      varinfo_t vi;
-
-      vi = get_vi_for_tree (var->decl);
-
-      /* Associate the varinfo node with all aliases.  */
-      for (alias = var->extra_name; alias; alias = alias->next)
-       insert_vi_for_tree (alias->decl, vi);
-    }
+      /* It does not make sense to have graph edges into or out of
+         externally visible functions.  There is no extra information
+        we can gather from them.  */
+      if (node->local.externally_visible)
+       continue;
 
 
-  if (dump_file)
-    {
-      fprintf (dump_file,
-              "Generating constraints for global initializers\n\n");
-      dump_constraints (dump_file, 0);
-      fprintf (dump_file, "\n");
+      create_function_info_for (node->decl,
+                               cgraph_node_name (node));
     }
     }
-  from = VEC_length (constraint_t, constraints);
 
   for (node = cgraph_nodes; node; node = node->next)
     {
 
   for (node = cgraph_nodes; node; node = node->next)
     {
@@ -6701,14 +5754,9 @@ ipa_pta_execute (void)
        continue;
 
       if (dump_file)
        continue;
 
       if (dump_file)
-       {
-         fprintf (dump_file,
-                  "Generating constraints for %s", cgraph_node_name (node));
-         if (DECL_ASSEMBLER_NAME_SET_P (node->decl))
-           fprintf (dump_file, " (%s)",
-                    IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
-         fprintf (dump_file, "\n");
-       }
+       fprintf (dump_file,
+                "Generating constraints for %s\n",
+                cgraph_node_name (node));
 
       func = DECL_STRUCT_FUNCTION (node->decl);
       old_func_decl = current_function_decl;
 
       func = DECL_STRUCT_FUNCTION (node->decl);
       old_func_decl = current_function_decl;
@@ -6740,204 +5788,16 @@ ipa_pta_execute (void)
              gimple stmt = gsi_stmt (gsi);
 
              find_func_aliases (stmt);
              gimple stmt = gsi_stmt (gsi);
 
              find_func_aliases (stmt);
-             find_func_clobbers (stmt);
            }
        }
 
       current_function_decl = old_func_decl;
       pop_cfun ();
            }
        }
 
       current_function_decl = old_func_decl;
       pop_cfun ();
-
-      if (dump_file)
-       {
-         fprintf (dump_file, "\n");
-         dump_constraints (dump_file, from);
-         fprintf (dump_file, "\n");
-       }
-      from = VEC_length (constraint_t, constraints);
     }
 
   /* From the constraints compute the points-to sets.  */
   solve_constraints ();
 
     }
 
   /* From the constraints compute the points-to sets.  */
   solve_constraints ();
 
-  /* Compute the global points-to sets for ESCAPED.
-     ???  Note that the computed escape set is not correct
-     for the whole unit as we fail to consider graph edges to
-     externally visible functions.  */
-  find_what_var_points_to (get_varinfo (escaped_id), &ipa_escaped_pt);
-
-  /* Make sure the ESCAPED solution (which is used as placeholder in
-     other solutions) does not reference itself.  This simplifies
-     points-to solution queries.  */
-  ipa_escaped_pt.ipa_escaped = 0;
-
-  /* Assign the points-to sets to the SSA names in the unit.  */
-  for (node = cgraph_nodes; node; node = node->next)
-    {
-      tree ptr;
-      struct function *fn;
-      unsigned i;
-      varinfo_t fi;
-      basic_block bb;
-      struct pt_solution uses, clobbers;
-      struct cgraph_edge *e;
-
-      /* Nodes without a body are not interesting.  */
-      if (!gimple_has_body_p (node->decl)
-         || node->clone_of)
-       continue;
-
-      fn = DECL_STRUCT_FUNCTION (node->decl);
-
-      /* Compute the points-to sets for pointer SSA_NAMEs.  */
-      for (i = 0; VEC_iterate (tree, fn->gimple_df->ssa_names, i, ptr); ++i)
-       {
-         if (ptr
-             && POINTER_TYPE_P (TREE_TYPE (ptr)))
-           find_what_p_points_to (ptr);
-       }
-
-      /* Compute the call-use and call-clobber sets for all direct calls.  */
-      fi = lookup_vi_for_tree (node->decl);
-      gcc_assert (fi->is_fn_info);
-      find_what_var_points_to (first_vi_for_offset (fi, fi_clobbers),
-                              &clobbers);
-      find_what_var_points_to (first_vi_for_offset (fi, fi_uses), &uses);
-      for (e = node->callers; e; e = e->next_caller)
-       {
-         if (!e->call_stmt)
-           continue;
-
-         *gimple_call_clobber_set (e->call_stmt) = clobbers;
-         *gimple_call_use_set (e->call_stmt) = uses;
-       }
-
-      /* Compute the call-use and call-clobber sets for indirect calls
-        and calls to external functions.  */
-      FOR_EACH_BB_FN (bb, fn)
-       {
-         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;
-             varinfo_t vi;
-             tree decl;
-
-             if (!is_gimple_call (stmt))
-               continue;
-
-             /* Handle direct calls to external functions.  */
-             decl = gimple_call_fndecl (stmt);
-             if (decl
-                 && (!(fi = lookup_vi_for_tree (decl))
-                     || !fi->is_fn_info))
-               {
-                 pt = gimple_call_use_set (stmt);
-                 if (gimple_call_flags (stmt) & ECF_CONST)
-                   memset (pt, 0, sizeof (struct pt_solution));
-                 else if ((vi = lookup_call_use_vi (stmt)) != NULL)
-                   {
-                     find_what_var_points_to (vi, pt);
-                     /* Escaped (and thus nonlocal) variables are always
-                        implicitly used by calls.  */
-                     /* ???  ESCAPED can be empty even though NONLOCAL
-                        always escaped.  */
-                     pt->nonlocal = 1;
-                     pt->ipa_escaped = 1;
-                   }
-                 else
-                   {
-                     /* If there is nothing special about this call then
-                        we have made everything that is used also escape.  */
-                     *pt = ipa_escaped_pt;
-                     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 if ((vi = lookup_call_clobber_vi (stmt)) != NULL)
-                   {
-                     find_what_var_points_to (vi, pt);
-                     /* Escaped (and thus nonlocal) variables are always
-                        implicitly clobbered by calls.  */
-                     /* ???  ESCAPED can be empty even though NONLOCAL
-                        always escaped.  */
-                     pt->nonlocal = 1;
-                     pt->ipa_escaped = 1;
-                   }
-                 else
-                   {
-                     /* If there is nothing special about this call then
-                        we have made everything that is used also escape.  */
-                     *pt = ipa_escaped_pt;
-                     pt->nonlocal = 1;
-                   }
-               }
-
-             /* Handle indirect calls.  */
-             if (!decl
-                 && (fi = get_fi_for_callee (stmt)))
-               {
-                 /* We need to accumulate all clobbers/uses of all possible
-                    callees.  */
-                 fi = get_varinfo (find (fi->id));
-                 /* If we cannot constrain the set of functions we'll end up
-                    calling we end up using/clobbering everything.  */
-                 if (bitmap_bit_p (fi->solution, anything_id)
-                     || bitmap_bit_p (fi->solution, nonlocal_id)
-                     || bitmap_bit_p (fi->solution, escaped_id))
-                   {
-                     pt_solution_reset (gimple_call_clobber_set (stmt));
-                     pt_solution_reset (gimple_call_use_set (stmt));
-                   }
-                 else
-                   {
-                     bitmap_iterator bi;
-                     unsigned i;
-                     struct pt_solution *uses, *clobbers;
-
-                     uses = gimple_call_use_set (stmt);
-                     clobbers = gimple_call_clobber_set (stmt);
-                     memset (uses, 0, sizeof (struct pt_solution));
-                     memset (clobbers, 0, sizeof (struct pt_solution));
-                     EXECUTE_IF_SET_IN_BITMAP (fi->solution, 0, i, bi)
-                       {
-                         struct pt_solution sol;
-
-                         vi = get_varinfo (i);
-                         if (!vi->is_fn_info)
-                           {
-                             /* ???  We could be more precise here?  */
-                             uses->nonlocal = 1;
-                             uses->ipa_escaped = 1;
-                             clobbers->nonlocal = 1;
-                             clobbers->ipa_escaped = 1;
-                             continue;
-                           }
-
-                         if (!uses->anything)
-                           {
-                             find_what_var_points_to
-                                 (first_vi_for_offset (vi, fi_uses), &sol);
-                             pt_solution_ior_into (uses, &sol);
-                           }
-                         if (!clobbers->anything)
-                           {
-                             find_what_var_points_to
-                                 (first_vi_for_offset (vi, fi_clobbers), &sol);
-                             pt_solution_ior_into (clobbers, &sol);
-                           }
-                       }
-                   }
-               }
-           }
-       }
-
-      fn->gimple_df->ipa_pta = true;
-    }
-
   delete_points_to_sets ();
 
   in_ipa_mode = 0;
   delete_points_to_sets ();
 
   in_ipa_mode = 0;
index e67f580..e0d3f48 100644 (file)
@@ -23,13 +23,14 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
+#include "rtl.h"
 #include "tm_p.h"
 #include "tm_p.h"
+#include "hard-reg-set.h"
 #include "basic-block.h"
 #include "function.h"
 #include "tree-flow.h"
 #include "tree-dump.h"
 #include "diagnostic.h"
 #include "basic-block.h"
 #include "function.h"
 #include "tree-flow.h"
 #include "tree-dump.h"
 #include "diagnostic.h"
-#include "gimple-pretty-print.h"
 #include "except.h"
 #include "tree-pass.h"
 #include "flags.h"
 #include "except.h"
 #include "tree-pass.h"
 #include "flags.h"
@@ -129,9 +130,32 @@ static void find_tail_calls (basic_block, struct tailcall **);
 static bool
 suitable_for_tail_opt_p (void)
 {
 static bool
 suitable_for_tail_opt_p (void)
 {
+  referenced_var_iterator rvi;
+  tree var;
+
   if (cfun->stdarg)
     return false;
 
   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;
+    }
+
   return true;
 }
 /* Returns false when the function is not suitable for tail call optimization
   return true;
 }
 /* Returns false when the function is not suitable for tail call optimization
@@ -363,8 +387,6 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
   tree m, a;
   basic_block abb;
   size_t idx;
   tree m, a;
   basic_block abb;
   size_t idx;
-  tree var;
-  referenced_var_iterator rvi;
 
   if (!single_succ_p (bb))
     return;
 
   if (!single_succ_p (bb))
     return;
@@ -420,7 +442,8 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
   func = gimple_call_fndecl (call);
   if (func == current_function_decl)
     {
   func = gimple_call_fndecl (call);
   if (func == current_function_decl)
     {
-      tree arg;
+      tree arg, var;
+      referenced_var_iterator rvi;
 
       for (param = DECL_ARGUMENTS (func), idx = 0;
           param && idx < gimple_call_num_args (call);
 
       for (param = DECL_ARGUMENTS (func), idx = 0;
           param && idx < gimple_call_num_args (call);
@@ -451,17 +474,15 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
        }
       if (idx == gimple_call_num_args (call) && !param)
        tail_recursion = true;
        }
       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 (TREE_CODE (var) != PARM_DECL
-         && auto_var_in_fn_p (var, cfun->decl)
-         && (ref_maybe_used_by_stmt_p (call, var)
-             || call_may_clobber_ref_p (call, var)))
-       return;
+      /* 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
     }
 
   /* Now check the statements after the call.  None of them has virtual
@@ -576,10 +597,13 @@ adjust_return_value_with_ops (enum tree_code code, const char *label,
 {
 
   tree ret_type = TREE_TYPE (DECL_RESULT (current_function_decl));
 {
 
   tree ret_type = TREE_TYPE (DECL_RESULT (current_function_decl));
-  tree tmp = create_tmp_reg (ret_type, label);
+  tree tmp = create_tmp_var (ret_type, label);
   gimple stmt;
   tree result;
 
   gimple stmt;
   tree result;
 
+  if (TREE_CODE (ret_type) == COMPLEX_TYPE
+      || TREE_CODE (ret_type) == VECTOR_TYPE)
+    DECL_GIMPLE_REG_P (tmp) = 1;
   add_referenced_var (tmp);
 
   if (types_compatible_p (TREE_TYPE (acc), TREE_TYPE (op1)))
   add_referenced_var (tmp);
 
   if (types_compatible_p (TREE_TYPE (acc), TREE_TYPE (op1)))
@@ -906,9 +930,12 @@ static tree
 create_tailcall_accumulator (const char *label, basic_block bb, tree init)
 {
   tree ret_type = TREE_TYPE (DECL_RESULT (current_function_decl));
 create_tailcall_accumulator (const char *label, basic_block bb, tree init)
 {
   tree ret_type = TREE_TYPE (DECL_RESULT (current_function_decl));
-  tree tmp = create_tmp_reg (ret_type, label);
+  tree tmp = create_tmp_var (ret_type, label);
   gimple phi;
 
   gimple phi;
 
+  if (TREE_CODE (ret_type) == COMPLEX_TYPE
+      || TREE_CODE (ret_type) == VECTOR_TYPE)
+    DECL_GIMPLE_REG_P (tmp) = 1;
   add_referenced_var (tmp);
   phi = create_phi_node (tmp, bb);
   /* RET_TYPE can be a float when -ffast-maths is enabled.  */
   add_referenced_var (tmp);
   phi = create_phi_node (tmp, bb);
   /* RET_TYPE can be a float when -ffast-maths is enabled.  */