PATCH cgraphunit.c: Don't revisit SAVE_EXPR nodes

Jeff Sturm jsturm@one-point.com
Wed Sep 3 05:16:00 GMT 2003


I discovered a pathological tree while building libjava with
-funit-at-a-time that consists of many nested compounds with SAVE_EXPR
nodes shared on both sides.  Seemingly this can cause an exponential
slowdown in cgraph_create_edges (or "virtual memory exhausted" in my
case).

walk_tree_without_duplicates would take care of the duplication, except
when called recursively, as happens at a CALL_EXPR node.

Following is my attempt at a fix.  Bootstrapped on mainline
for i686-pc-linux-gnu.

Jeff

2003-09-03  Jeff Sturm  <jsturm@one-point.com>

	* cgraphunit.c (visited_save_exprs): New static variable.
	(record_call_1): Remember visited SAVE_EXPR nodes.
	(cgraph_create_edges): Setup/teardown visited_save_exprs.

--- cgraphunit.c	2003-09-02 16:30:37.000000000 -0400
+++ cgraphunit.c.new	2003-09-02 16:20:43.000000000 -0400
@@ -54,6 +54,8 @@ static int nfunctions_inlined;
 static int initial_insns;
 static int overall_insns;

+static htab_t visited_save_exprs;
+
 /* Analyze function once it is parsed.  Set up the local information
    available - create cgraph edges for function calls via BODY.  */

@@ -127,6 +129,19 @@ record_call_1 (tree *tp, int *walk_subtr
 	  *walk_subtrees = 0;
 	}
     }
+  else if (TREE_CODE (*tp) == SAVE_EXPR)
+    {
+      void **slot;
+
+      /* Ensure we don't visit a SAVE_EXPR node more than once.
+	 In spite of walk_tree_without_duplicates, this may happen
+	 e.g. when a SAVE_EXPR appears in a parameter list.  */
+      slot = htab_find_slot (visited_save_exprs, *tp, INSERT);
+      if (*slot)
+	*walk_subtrees = 0;
+      else
+	*slot = *tp;
+    }
   /* Save some cycles by not walking types and declaration as we won't find anything
      usefull there anyway.  */
   if (DECL_P (*tp) || TYPE_P (*tp))
@@ -141,7 +156,11 @@ cgraph_create_edges (tree decl, tree bod
 {
   /* The nodes we're interested in are never shared, so walk
      the tree ignoring duplicates.  */
+  visited_save_exprs = htab_create (37, htab_hash_pointer,
+				    htab_eq_pointer, NULL);
   walk_tree_without_duplicates (&body, record_call_1, decl);
+  htab_delete (visited_save_exprs);
+  visited_save_exprs = NULL;
 }

 /* Analyze the function scheduled to be output.  */



More information about the Gcc-patches mailing list