This brings down compile-time in PTA from

 tree PTA                :  25.37 (24%) usr

to

 tree PTA                :   5.06 ( 6%) usr

by doing something that was on my TODO list for ... ages.  We
are currently re-translating internal points-to sets to final
points-to sets all the time even if we know the result will
be the same as one we computed already.  When a lot of points-to
sets are equivalent (as in the above testcase) we spend a lot
of time doing that useless work.

The following patch simply caches the result using a pointer-map
(instead of enlarging the varinfo struct).

For the testcase incremental SSA update is now the worst offender:

 tree SSA incremental    :  34.14 (39%) usr

out of a remaining total

 TOTAL                 :  86.53

(that's at -O1).

Bootstrap & regtest ongoing on x86_64-unknown-linux-gnu, scheduled
for a commit to trunk (generic compile-time regression, etc.).

Richard.

2013-01-29  Richard Biener  <rguent...@suse.de>

        * tree-ssa-structalias.c (final_solutions, final_solutions_obstack):
        New pointer-map and obstack.
        (init_alias_vars): Allocate pointer-map and obstack.
        (delete_points_to_sets): Free them.
        (find_what_var_points_to): Cache result.
        (find_what_p_points_to): Adjust for changed interface of
        find_what_var_points_to.
        (compute_points_to_sets): Likewise.
        (ipa_pta_execute): Likewise.

Index: gcc/tree-ssa-structalias.c
===================================================================
*** gcc/tree-ssa-structalias.c  (revision 195549)
--- gcc/tree-ssa-structalias.c  (working copy)
*************** static inline bool type_can_have_subvars
*** 303,309 ****
  /* Pool of variable info structures.  */
  static alloc_pool variable_info_pool;
  
! 
  
  /* Table of variable info structures for constraint variables.
     Indexed directly by variable info id.  */
--- 303,311 ----
  /* Pool of variable info structures.  */
  static alloc_pool variable_info_pool;
  
! /* Map varinfo to final pt_solution.  */
! static pointer_map_t *final_solutions;
! struct obstack final_solutions_obstack;
  
  /* Table of variable info structures for constraint variables.
     Indexed directly by variable info id.  */
*************** set_uids_in_ptset (bitmap into, bitmap f
*** 5872,5892 ****
  
  /* Compute the points-to solution *PT for the variable VI.  */
  
! static void
! find_what_var_points_to (varinfo_t orig_vi, struct pt_solution *pt)
  {
    unsigned int i;
    bitmap_iterator bi;
    bitmap finished_solution;
    bitmap result;
    varinfo_t vi;
! 
!   memset (pt, 0, sizeof (struct pt_solution));
  
    /* This variable may have been collapsed, let's get the real
       variable.  */
    vi = get_varinfo (find (orig_vi->id));
  
    /* Translate artificial variables into SSA_NAME_PTR_INFO
       attributes.  */
    EXECUTE_IF_SET_IN_BITMAP (vi->solution, 0, i, bi)
--- 5960,5988 ----
  
  /* Compute the points-to solution *PT for the variable VI.  */
  
! static struct pt_solution
! find_what_var_points_to (varinfo_t orig_vi)
  {
    unsigned int i;
    bitmap_iterator bi;
    bitmap finished_solution;
    bitmap result;
    varinfo_t vi;
!   void **slot;
!   struct pt_solution *pt;
  
    /* This variable may have been collapsed, let's get the real
       variable.  */
    vi = get_varinfo (find (orig_vi->id));
  
+   /* See if we have already computed the solution and return it.  */
+   slot = pointer_map_insert (final_solutions, vi);
+   if (*slot != NULL)
+     return *(struct pt_solution *)*slot;
+ 
+   *slot = pt = XOBNEW (&final_solutions_obstack, struct pt_solution);
+   memset (pt, 0, sizeof (struct pt_solution));
+ 
    /* Translate artificial variables into SSA_NAME_PTR_INFO
       attributes.  */
    EXECUTE_IF_SET_IN_BITMAP (vi->solution, 0, i, bi)
*************** find_what_var_points_to (varinfo_t orig_
*** 5921,5927 ****
    /* Instead of doing extra work, simply do not create
       elaborate points-to information for pt_anything pointers.  */
    if (pt->anything)
!     return;
  
    /* Share the final set of variables when possible.  */
    finished_solution = BITMAP_GGC_ALLOC ();
--- 6017,6023 ----
    /* Instead of doing extra work, simply do not create
       elaborate points-to information for pt_anything pointers.  */
    if (pt->anything)
!     return *pt;
  
    /* Share the final set of variables when possible.  */
    finished_solution = BITMAP_GGC_ALLOC ();
*************** find_what_var_points_to (varinfo_t orig_
*** 5939,5944 ****
--- 6035,6042 ----
        pt->vars = result;
        bitmap_clear (finished_solution);
      }
+ 
+   return *pt;
  }
  
  /* Given a pointer variable P, fill in its points-to set.  */
*************** find_what_p_points_to (tree p)
*** 5963,5969 ****
      return;
  
    pi = get_ptr_info (p);
!   find_what_var_points_to (vi, &pi->pt);
  }
  
  
--- 6061,6067 ----
      return;
  
    pi = get_ptr_info (p);
!   pi->pt = find_what_var_points_to (vi);
  }
  
  
*************** init_alias_vars (void)
*** 6480,6485 ****
--- 6578,6586 ----
    init_base_vars ();
  
    gcc_obstack_init (&fake_var_decl_obstack);
+ 
+   final_solutions = pointer_map_create ();
+   gcc_obstack_init (&final_solutions_obstack);
  }
  
  /* Remove the REF and ADDRESS edges from GRAPH, as well as all the
*************** compute_points_to_sets (void)
*** 6638,6645 ****
    solve_constraints ();
  
    /* Compute the points-to set for ESCAPED used for call-clobber analysis.  */
!   find_what_var_points_to (get_varinfo (escaped_id),
!                          &cfun->gimple_df->escaped);
  
    /* Make sure the ESCAPED solution (which is used as placeholder in
       other solutions) does not reference itself.  This simplifies
--- 6739,6745 ----
    solve_constraints ();
  
    /* Compute the points-to set for ESCAPED used for call-clobber analysis.  */
!   cfun->gimple_df->escaped = find_what_var_points_to (get_varinfo 
(escaped_id));
  
    /* Make sure the ESCAPED solution (which is used as placeholder in
       other solutions) does not reference itself.  This simplifies
*************** compute_points_to_sets (void)
*** 6679,6685 ****
            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
--- 6779,6785 ----
            memset (pt, 0, sizeof (struct pt_solution));
          else if ((vi = lookup_call_use_vi (stmt)) != NULL)
            {
!             *pt = find_what_var_points_to (vi);
              /* Escaped (and thus nonlocal) variables are always
                 implicitly used by calls.  */
              /* ???  ESCAPED can be empty even though NONLOCAL
*************** compute_points_to_sets (void)
*** 6700,6706 ****
            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
--- 6800,6806 ----
            memset (pt, 0, sizeof (struct pt_solution));
          else if ((vi = lookup_call_clobber_vi (stmt)) != NULL)
            {
!             *pt = find_what_var_points_to (vi);
              /* Escaped (and thus nonlocal) variables are always
                 implicitly clobbered by calls.  */
              /* ???  ESCAPED can be empty even though NONLOCAL
*************** delete_points_to_sets (void)
*** 6755,6760 ****
--- 6855,6863 ----
    free_alloc_pool (constraint_pool);
  
    obstack_free (&fake_var_decl_obstack, NULL);
+ 
+   pointer_map_destroy (final_solutions);
+   obstack_free (&final_solutions_obstack, NULL);
  }
  
  
*************** ipa_pta_execute (void)
*** 7023,7029 ****
       ???  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
--- 7126,7132 ----
       ???  Note that the computed escape set is not correct
       for the whole unit as we fail to consider graph edges to
       externally visible functions.  */
!   ipa_escaped_pt = find_what_var_points_to (get_varinfo (escaped_id));
  
    /* Make sure the ESCAPED solution (which is used as placeholder in
       other solutions) does not reference itself.  This simplifies
*************** ipa_pta_execute (void)
*** 7058,7066 ****
        /* Compute the call-use and call-clobber sets for all direct calls.  */
        fi = lookup_vi_for_tree (node->symbol.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)
--- 7161,7169 ----
        /* Compute the call-use and call-clobber sets for all direct calls.  */
        fi = lookup_vi_for_tree (node->symbol.decl);
        gcc_assert (fi->is_fn_info);
!       clobbers
!       = find_what_var_points_to (first_vi_for_offset (fi, fi_clobbers));
!       uses = find_what_var_points_to (first_vi_for_offset (fi, fi_uses));
        for (e = node->callers; e; e = e->next_caller)
        {
          if (!e->call_stmt)
*************** ipa_pta_execute (void)
*** 7097,7103 ****
                    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
--- 7200,7206 ----
                    memset (pt, 0, sizeof (struct pt_solution));
                  else if ((vi = lookup_call_use_vi (stmt)) != NULL)
                    {
!                     *pt = find_what_var_points_to (vi);
                      /* Escaped (and thus nonlocal) variables are always
                         implicitly used by calls.  */
                      /* ???  ESCAPED can be empty even though NONLOCAL
*************** ipa_pta_execute (void)
*** 7118,7124 ****
                    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
--- 7221,7227 ----
                    memset (pt, 0, sizeof (struct pt_solution));
                  else if ((vi = lookup_call_clobber_vi (stmt)) != NULL)
                    {
!                     *pt = find_what_var_points_to (vi);
                      /* Escaped (and thus nonlocal) variables are always
                         implicitly clobbered by calls.  */
                      /* ???  ESCAPED can be empty even though NONLOCAL
*************** ipa_pta_execute (void)
*** 7178,7191 ****
  
                          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);
                            }
                        }
--- 7281,7294 ----
  
                          if (!uses->anything)
                            {
!                             sol = find_what_var_points_to
!                                     (first_vi_for_offset (vi, fi_uses));
                              pt_solution_ior_into (uses, &sol);
                            }
                          if (!clobbers->anything)
                            {
!                             sol = find_what_var_points_to
!                                     (first_vi_for_offset (vi, fi_clobbers));
                              pt_solution_ior_into (clobbers, &sol);
                            }
                        }

Reply via email to