This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


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

C++: Revised patch improving walk_tree and prune_unused_decls a bit


This is a slightly revised version of the patch I posted to gcc-bugs
earlier today (see thread "Example program takes 2000 times as long to
compile under C++ as C").  It turns out we still do need to dink with
the current line number in walk_tree.  The patch is otherwise
identical.

The original patch survived a complete bootstrap and testsuite.  This
one survived the C++ test suite and in addition doesn't mess up
g++.pt/crash6.C at -O.

Reviewed by Mark Mitchell.  Applied.

zw

cp:
        * tree.c (walk_tree): Expose tail recursion.
        (walk_stmt_tree): New function.
        * cp-tree.h: Prototype walk_stmt_tree.
        * semantics.c (prune_unused_decls): Operate on SCOPE_STMTs not
        the BLOCKs directly.  If a BLOCK has no variables after
        pruning, discard it.
        (finish_stmt_tree): Use walk_stmt_tree.  No need to save and
        restore the line number.

===================================================================
Index: cp/cp-tree.h
--- cp/cp-tree.h	2000/09/05 07:31:26	1.521
+++ cp/cp-tree.h	2000/09/06 05:50:30
@@ -4543,6 +4543,9 @@ extern tree walk_tree                   
 extern tree walk_tree_without_duplicates        PARAMS ((tree *,
 							 walk_tree_fn,
 							 void *));
+extern tree walk_stmt_tree			PARAMS ((tree *,
+							 walk_tree_fn,
+							 void *));
 extern tree copy_tree_r                         PARAMS ((tree *, int *, void *));
 extern int cp_valid_lang_attribute		PARAMS ((tree, tree, tree, tree));
 extern tree make_ptrmem_cst                     PARAMS ((tree, tree));
===================================================================
Index: cp/semantics.c
--- cp/semantics.c	2000/09/05 07:31:27	1.166
+++ cp/semantics.c	2000/09/06 05:50:31
@@ -2274,21 +2274,28 @@ prune_unused_decls (tp, walk_subtrees, d
 	  return prune_unused_decls (tp, walk_subtrees, data);
 	}
     }
-  else if (TREE_CODE (t) == BLOCK)
+  else if (TREE_CODE (t) == SCOPE_STMT)
     {
-      /* walk_tree doesn't inspect BLOCK_VARS, so we must do it by hand.  */
-      tree *vp;
+      /* Remove all unused decls from the BLOCK of this SCOPE_STMT.  */
+      tree block = SCOPE_STMT_BLOCK (t);
 
-      for (vp = &BLOCK_VARS (t); *vp; )
+      if (block)
 	{
-	  tree v = *vp;
-	  if (! TREE_USED (v) && DECL_NAME (v) && DECL_SOURCE_LINE (v) == 0)
-	    *vp = TREE_CHAIN (v);  /* drop */
-	  else
-	    vp = &TREE_CHAIN (v);  /* advance */
+	  tree *vp;
+
+	  for (vp = &BLOCK_VARS (block); *vp; )
+	    {
+	      tree v = *vp;
+	      if (! TREE_USED (v) && DECL_NAME (v) && DECL_SOURCE_LINE (v) == 0)
+		*vp = TREE_CHAIN (v);  /* drop */
+	      else
+		vp = &TREE_CHAIN (v);  /* advance */
+	    }
+	  /* If there are now no variables, the entire BLOCK can be dropped.
+	     (This causes SCOPE_NULLIFIED_P (t) to be true.)  */
+	  if (BLOCK_VARS (block) == NULL_TREE)
+	    SCOPE_STMT_BLOCK (t) = NULL_TREE;
 	}
-      if (BLOCK_VARS (t) == NULL_TREE)
-	TREE_USED (t) = 0;
     }
   return NULL_TREE;
 }
@@ -2314,18 +2321,14 @@ finish_stmt_tree (t)
      tree *t;
 {
   tree stmt;
-  int old_lineno;
   
   /* Remove the fake extra statement added in begin_stmt_tree.  */
   stmt = TREE_CHAIN (*t);
   *t = stmt;
   SET_LAST_STMT (NULL_TREE);
 
-  /* Remove unused decls from the stmt tree.  walk_tree messes with
-     the line number, so save/restore it.  */
-  old_lineno = lineno;
-  walk_tree_without_duplicates (t, prune_unused_decls, NULL);
-  lineno = old_lineno;
+  /* Remove unused decls from the stmt tree.  */
+  walk_stmt_tree (t, prune_unused_decls, NULL);
 
   if (cfun)
     {
===================================================================
Index: cp/tree.c
--- cp/tree.c	2000/09/05 07:31:27	1.213
+++ cp/tree.c	2000/09/06 05:50:31
@@ -1319,7 +1319,8 @@ walk_tree (tp, func, data, htab)
 	      WALK_SUBTREE (DECL_SIZE_UNIT (DECL_STMT_DECL (*tp)));
 	    }
 
-	  WALK_SUBTREE (TREE_CHAIN (*tp));
+	  /* This can be tail-recursion optimized if we write it this way.  */
+	  return walk_tree (&TREE_CHAIN (*tp), func, data, htab);
 	}
 
       /* We didn't find what we were looking for.  */
@@ -1452,6 +1453,73 @@ walk_tree_without_duplicates (tp, func, 
   result = walk_tree (tp, func, data, htab);
   htab_delete (htab);
   return result;
+}
+
+/* Like walk_tree, but only examines statement nodes.  We don't need a
+   without_duplicates variant of this one because the statement tree is
+   a tree, not a graph.  */
+
+tree 
+walk_stmt_tree (tp, func, data)
+     tree *tp;
+     walk_tree_fn func;
+     void *data;
+{
+  enum tree_code code;
+  int walk_subtrees;
+  tree result;
+  int i, len;
+
+#define WALK_SUBTREE(NODE)				\
+  do							\
+    {							\
+      result = walk_stmt_tree (&(NODE), func, data);	\
+      if (result)					\
+	return result;					\
+    }							\
+  while (0)
+
+  /* Skip empty subtrees.  */
+  if (!*tp)
+    return NULL_TREE;
+
+  /* Skip subtrees below non-statement nodes.  */
+  if (!statement_code_p (TREE_CODE (*tp)))
+    return NULL_TREE;
+
+  /* Call the function.  */
+  walk_subtrees = 1;
+  result = (*func) (tp, &walk_subtrees, data);
+
+  /* If we found something, return it.  */
+  if (result)
+    return result;
+
+  /* Even if we didn't, FUNC may have decided that there was nothing
+     interesting below this point in the tree.  */
+  if (!walk_subtrees)
+    return NULL_TREE;
+
+  /* FUNC may have modified the tree, recheck that we're looking at a
+     statement node.  */
+  code = TREE_CODE (*tp);
+  if (!statement_code_p (code))
+    return NULL_TREE;
+
+  /* Walk over all the sub-trees of this operand.  Statement nodes never
+     contain RTL, and we needn't worry about TARGET_EXPRs.  */
+  len = TREE_CODE_LENGTH (code);
+
+  /* Go through the subtrees.  We need to do this in forward order so
+     that the scope of a FOR_EXPR is handled properly.  */
+  for (i = 0; i < len; ++i)
+    WALK_SUBTREE (TREE_OPERAND (*tp, i));
+
+  /* Finally visit the chain.  This can be tail-recursion optimized if
+     we write it this way.  */
+  return walk_stmt_tree (&TREE_CHAIN (*tp), func, data);
+
+#undef WALK_SUBTREE
 }
 
 /* Called from count_trees via walk_tree.  */

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