re PR tree-optimization/46590 (long compile time with -O2 and many loops)
authorRichard Guenther <rguenther@suse.de>
Wed, 22 Aug 2012 13:17:26 +0000 (13:17 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Wed, 22 Aug 2012 13:17:26 +0000 (13:17 +0000)
2012-08-22  Richard Guenther  <rguenther@suse.de>

PR tree-optimization/46590
* tree-ssa-alias.h (get_continuation_for_phi): Add alias query
counter output argument.
(walk_non_aliased_vuses): Add alias query counter argument
to the walker callback.
* tree-ssa-alias.c (maybe_skip_until): Add alias query counter
output argument and count alias queries.
(get_continuation_for_phi_1): Likewise.
(get_continuation_for_phi): Likewise.
(walk_non_aliased_vuses): Add alias query counter argument
to the walker callback and allow it to abort the walk by
returning -1.
* tree-ssa-pre.c (translate_vuse_through_block): Adjust.
* tree-ssa-sccvn.c (vn_reference_lookup_2): Add alias query
counter parmeter, abort walk if that is bigger than
--param sccvn-max-alias-queries-per-access.
* params.def (sccvn-max-alias-queries-per-access): New param.
* doc/invoke.texi (sccvn-max-alias-queries-per-access): Document.

From-SVN: r190594

gcc/ChangeLog
gcc/doc/invoke.texi
gcc/params.def
gcc/tree-ssa-alias.c
gcc/tree-ssa-alias.h
gcc/tree-ssa-pre.c
gcc/tree-ssa-sccvn.c

index 1fec0b852a1b58436a6e73412f44921e5592f56d..75cd34c49b2d8d62f917add9b7868bcc6c63dd99 100644 (file)
@@ -1,3 +1,24 @@
+2012-08-22  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/46590
+       * tree-ssa-alias.h (get_continuation_for_phi): Add alias query
+       counter output argument.
+       (walk_non_aliased_vuses): Add alias query counter argument
+       to the walker callback.
+       * tree-ssa-alias.c (maybe_skip_until): Add alias query counter
+       output argument and count alias queries.
+       (get_continuation_for_phi_1): Likewise.
+       (get_continuation_for_phi): Likewise.
+       (walk_non_aliased_vuses): Add alias query counter argument
+       to the walker callback and allow it to abort the walk by
+       returning -1.
+       * tree-ssa-pre.c (translate_vuse_through_block): Adjust.
+       * tree-ssa-sccvn.c (vn_reference_lookup_2): Add alias query
+       counter parmeter, abort walk if that is bigger than
+       --param sccvn-max-alias-queries-per-access.
+       * params.def (sccvn-max-alias-queries-per-access): New param.
+       * doc/invoke.texi (sccvn-max-alias-queries-per-access): Document.
+
 2012-08-22  Richard Guenther  <rguenther@suse.de>
 
        * tree-ssa-loop-ch.c (copy_loop_headers): Remove redundant checking.
index ae22ca9aa0c4115199b1064ec500e9fe7c425564..599b0f6f0551429c46e8d2ed261bfcd92bf467cc 100644 (file)
@@ -9221,6 +9221,14 @@ processing.  If this limit is hit, SCCVN processing for the whole
 function is not done and optimizations depending on it are
 disabled.  The default maximum SCC size is 10000.
 
+@item sccvn-max-alias-queries-per-access
+Maximum number of alias-oracle queries we perform when looking for
+redundancies for loads and stores.  If this limit is hit the search
+is aborted and the load or store is not considered redundant.  The
+number of queries is algorithmically limited to the number of
+stores on all paths from the load to the function entry.
+The default maxmimum number of queries is 1000.
+
 @item ira-max-loops-num
 IRA uses regional register allocation by default.  If a function
 contains more loops than the number given by this parameter, only at most
index cd8cb22998f39958a261ab0707f46813268ae980..17351bf005282148a06042557eb9e5e6e96f4635 100644 (file)
@@ -752,6 +752,17 @@ DEFPARAM (PARAM_SCCVN_MAX_SCC_SIZE,
          "Maximum size of a SCC before SCCVN stops processing a function",
          10000, 10, 0)
 
+/* The following is used as a stop-gap limit for cases where really huge
+   functions blow up compile-time use too much.  It limits the number of
+   alias-queries we do for finding common subexpressions for memory loads and
+   stores.  The number of alias-queries is otherwise limited by the number of
+   stores on paths to function entry.  */
+
+DEFPARAM (PARAM_SCCVN_MAX_ALIAS_QUERIES_PER_ACCESS,
+         "sccvn-max-alias-queries-per-access",
+         "Maximum number of disambiguations to perform per memory access",
+         1000, 0, 0)
+
 DEFPARAM (PARAM_IRA_MAX_LOOPS_NUM,
          "ira-max-loops-num",
          "Max loops number for regional RA",
index be0aa432b4f28dea137756229525147f3ffed1a6..574f418447d42f5fa3fd73c980be08d9e97625f0 100644 (file)
@@ -1929,7 +1929,7 @@ stmt_kills_ref_p (gimple stmt, tree ref)
 
 static bool
 maybe_skip_until (gimple phi, tree target, ao_ref *ref,
-                 tree vuse, bitmap *visited)
+                 tree vuse, unsigned int *cnt, bitmap *visited)
 {
   basic_block bb = gimple_bb (phi);
 
@@ -1948,15 +1948,20 @@ maybe_skip_until (gimple phi, tree target, ao_ref *ref,
          /* An already visited PHI node ends the walk successfully.  */
          if (bitmap_bit_p (*visited, SSA_NAME_VERSION (PHI_RESULT (def_stmt))))
            return true;
-         vuse = get_continuation_for_phi (def_stmt, ref, visited);
+         vuse = get_continuation_for_phi (def_stmt, ref, cnt, visited);
          if (!vuse)
            return false;
          continue;
        }
-      /* A clobbering statement or the end of the IL ends it failing.  */
-      else if (gimple_nop_p (def_stmt)
-              || stmt_may_clobber_ref_p_1 (def_stmt, ref))
+      else if (gimple_nop_p (def_stmt))
        return false;
+      else
+       {
+         /* A clobbering statement or the end of the IL ends it failing.  */
+         ++*cnt;
+         if (stmt_may_clobber_ref_p_1 (def_stmt, ref))
+           return false;
+       }
       /* If we reach a new basic-block see if we already skipped it
          in a previous walk that ended successfully.  */
       if (gimple_bb (def_stmt) != bb)
@@ -1976,7 +1981,7 @@ maybe_skip_until (gimple phi, tree target, ao_ref *ref,
 
 static tree
 get_continuation_for_phi_1 (gimple phi, tree arg0, tree arg1,
-                           ao_ref *ref, bitmap *visited)
+                           ao_ref *ref, unsigned int *cnt, bitmap *visited)
 {
   gimple def0 = SSA_NAME_DEF_STMT (arg0);
   gimple def1 = SSA_NAME_DEF_STMT (arg1);
@@ -1989,14 +1994,14 @@ get_continuation_for_phi_1 (gimple phi, tree arg0, tree arg1,
               && dominated_by_p (CDI_DOMINATORS,
                                  gimple_bb (def1), gimple_bb (def0))))
     {
-      if (maybe_skip_until (phi, arg0, ref, arg1, visited))
+      if (maybe_skip_until (phi, arg0, ref, arg1, cnt, visited))
        return arg0;
     }
   else if (gimple_nop_p (def1)
           || dominated_by_p (CDI_DOMINATORS,
                              gimple_bb (def0), gimple_bb (def1)))
     {
-      if (maybe_skip_until (phi, arg1, ref, arg0, visited))
+      if (maybe_skip_until (phi, arg1, ref, arg0, cnt, visited))
        return arg1;
     }
   /* Special case of a diamond:
@@ -2015,6 +2020,7 @@ get_continuation_for_phi_1 (gimple phi, tree arg0, tree arg1,
   else if ((common_vuse = gimple_vuse (def0))
           && common_vuse == gimple_vuse (def1))
     {
+      *cnt += 2;
       if (!stmt_may_clobber_ref_p_1 (def0, ref)
          && !stmt_may_clobber_ref_p_1 (def1, ref))
        return common_vuse;
@@ -2027,11 +2033,12 @@ get_continuation_for_phi_1 (gimple phi, tree arg0, tree arg1,
 /* Starting from a PHI node for the virtual operand of the memory reference
    REF find a continuation virtual operand that allows to continue walking
    statements dominating PHI skipping only statements that cannot possibly
-   clobber REF.  Returns NULL_TREE if no suitable virtual operand can
-   be found.  */
+   clobber REF.  Increments *CNT for each alias disambiguation done.
+   Returns NULL_TREE if no suitable virtual operand can be found.  */
 
 tree
-get_continuation_for_phi (gimple phi, ao_ref *ref, bitmap *visited)
+get_continuation_for_phi (gimple phi, ao_ref *ref,
+                         unsigned int *cnt, bitmap *visited)
 {
   unsigned nargs = gimple_phi_num_args (phi);
 
@@ -2068,7 +2075,8 @@ get_continuation_for_phi (gimple phi, ao_ref *ref, bitmap *visited)
       for (i = 0; i < nargs; ++i)
        {
          arg1 = PHI_ARG_DEF (phi, i);
-         arg0 = get_continuation_for_phi_1 (phi, arg0, arg1, ref, visited);
+         arg0 = get_continuation_for_phi_1 (phi, arg0, arg1, ref,
+                                            cnt, visited);
          if (!arg0)
            return NULL_TREE;
        }
@@ -2099,11 +2107,12 @@ get_continuation_for_phi (gimple phi, ao_ref *ref, bitmap *visited)
 
 void *
 walk_non_aliased_vuses (ao_ref *ref, tree vuse,
-                       void *(*walker)(ao_ref *, tree, void *),
+                       void *(*walker)(ao_ref *, tree, unsigned int, void *),
                        void *(*translate)(ao_ref *, tree, void *), void *data)
 {
   bitmap visited = NULL;
   void *res;
+  unsigned int cnt = 0;
 
   timevar_push (TV_ALIAS_STMT_WALK);
 
@@ -2112,17 +2121,25 @@ walk_non_aliased_vuses (ao_ref *ref, tree vuse,
       gimple def_stmt;
 
       /* ???  Do we want to account this to TV_ALIAS_STMT_WALK?  */
-      res = (*walker) (ref, vuse, data);
-      if (res)
+      res = (*walker) (ref, vuse, cnt, data);
+      /* Abort walk.  */
+      if (res == (void *)-1)
+       {
+         res = NULL;
+         break;
+       }
+      /* Lookup succeeded.  */
+      else if (res != NULL)
        break;
 
       def_stmt = SSA_NAME_DEF_STMT (vuse);
       if (gimple_nop_p (def_stmt))
        break;
       else if (gimple_code (def_stmt) == GIMPLE_PHI)
-       vuse = get_continuation_for_phi (def_stmt, ref, &visited);
+       vuse = get_continuation_for_phi (def_stmt, ref, &cnt, &visited);
       else
        {
+         cnt++;
          if (stmt_may_clobber_ref_p_1 (def_stmt, ref))
            {
              if (!translate)
index f3505432793d549eb92be179223a22ff6b2e4021..cdff3812181c21e9352f5b385ecb26028c7fe8ac 100644 (file)
@@ -107,9 +107,11 @@ extern bool stmt_may_clobber_ref_p (gimple, tree);
 extern bool stmt_may_clobber_ref_p_1 (gimple, ao_ref *);
 extern bool call_may_clobber_ref_p (gimple, tree);
 extern bool stmt_kills_ref_p (gimple, tree);
-extern tree get_continuation_for_phi (gimple, ao_ref *, bitmap *);
+extern tree get_continuation_for_phi (gimple, ao_ref *,
+                                     unsigned int *, bitmap *);
 extern void *walk_non_aliased_vuses (ao_ref *, tree,
-                                    void *(*)(ao_ref *, tree, void *),
+                                    void *(*)(ao_ref *, tree,
+                                              unsigned int, void *),
                                     void *(*)(ao_ref *, tree, void *), void *);
 extern unsigned int walk_aliased_vdefs (ao_ref *, tree,
                                        bool (*)(ao_ref *, tree, void *),
index e1135395f65746fdd3a06e0921dc287fb50c98cd..6d10df87a0e48c204246acf5c5bc6fc4ed1c5177 100644 (file)
@@ -1289,9 +1289,10 @@ translate_vuse_through_block (VEC (vn_reference_op_s, heap) *operands,
       if (use_oracle)
        {
          bitmap visited = NULL;
+         unsigned int cnt;
          /* Try to find a vuse that dominates this phi node by skipping
             non-clobbering statements.  */
-         vuse = get_continuation_for_phi (phi, &ref, &visited);
+         vuse = get_continuation_for_phi (phi, &ref, &cnt, &visited);
          if (visited)
            BITMAP_FREE (visited);
        }
index 216d3f647e9cc7f954b619094e86d56dff4ef728..5d5a91cef7ce5e962c23e242f55e301413fe432a 100644 (file)
@@ -1330,12 +1330,19 @@ static vn_lookup_kind default_vn_walk_kind;
    with the current VUSE and performs the expression lookup.  */
 
 static void *
-vn_reference_lookup_2 (ao_ref *op ATTRIBUTE_UNUSED, tree vuse, void *vr_)
+vn_reference_lookup_2 (ao_ref *op ATTRIBUTE_UNUSED, tree vuse,
+                      unsigned int cnt, void *vr_)
 {
   vn_reference_t vr = (vn_reference_t)vr_;
   void **slot;
   hashval_t hash;
 
+  /* This bounds the stmt walks we perform on reference lookups
+     to O(1) instead of O(N) where N is the number of dominating
+     stores.  */
+  if (cnt > (unsigned) PARAM_VALUE (PARAM_SCCVN_MAX_ALIAS_QUERIES_PER_ACCESS))
+    return (void *)-1;
+
   if (last_vuse_ptr)
     *last_vuse_ptr = vuse;