attribute((leafify)) for 3.4

Richard Guenther rguenth@tat.physik.uni-tuebingen.de
Thu Oct 30 19:07:00 GMT 2003


On Thu, 30 Oct 2003, Jan Hubicka wrote:

> > On Mon, 27 Oct 2003, Richard Guenther wrote:
> >
> > My idea was to add a maybe_inline_call flag to the cgraph edges and use
> > this the same as the inline_call flag at topological sorting time, but
> > treat it the same as inline_call flag only if assembling a function decl
> > with attribute((leafify)) set.
>
> I actually was playing with similar idea too.  It is quite easy to get
> it basically working by modifying inline_call_p candidate to know
> whether it is called for leafifed function or not.
>
> However there are several places where inline_call flag matters.  It is
> used to determine whether off-line version of function is needed on
> several places, also it is used for code size growth estimation code.
> All this would significantly get confused by doing non-transitive
> inlining.
>
> It seems to me that we should try to get this done by assigning separate
> cgraph nodes to the function clones.  It would result in better global
> dataflow sollutions too and would simplify logic of several other
> places.
>
> What about giving up the attribute for 3.4 (we are in feature freeze
> already anyway) and doing so on tree-ssa?  I will prepare the cleanups
> during next week so we can make progress on it.

Well, I wouldnt need to have it in official 3.4, I just use a locally
patched gcc for my work. Btw. I tried the above (but obviously missed some
parts, as it doesnt work), see attached patch. I somehow circumvented most
of the problems you mention above, but it seems the functions are not
considered for inlining though cgraph_inline_p is modified to honour
the case of a callee of a leafify function (you didnt mean
cgraph_inline_p by inline_call_p?).

Richard.

--
Richard Guenther <richard dot guenther at uni-tuebingen dot de>
WWW: http://www.tat.physik.uni-tuebingen.de/~rguenth/
-------------- next part --------------
Index: c-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.465
diff -u -u -r1.465 c-common.c
--- c-common.c	20 Oct 2003 22:03:32 -0000	1.465
+++ c-common.c	30 Oct 2003 14:04:50 -0000
@@ -762,6 +762,7 @@
 static tree handle_noinline_attribute (tree *, tree, tree, int, bool *);
 static tree handle_always_inline_attribute (tree *, tree, tree, int,
 					    bool *);
+static tree handle_leafify_attribute (tree *, tree, tree, int, bool *);
 static tree handle_used_attribute (tree *, tree, tree, int, bool *);
 static tree handle_unused_attribute (tree *, tree, tree, int, bool *);
 static tree handle_const_attribute (tree *, tree, tree, int, bool *);
@@ -824,6 +825,8 @@
 			      handle_noinline_attribute },
   { "always_inline",          0, 0, true,  false, false,
 			      handle_always_inline_attribute },
+  { "leafify",                0, 0, true,  false, false,
+			      handle_leafify_attribute },
   { "used",                   0, 0, true,  false, false,
 			      handle_used_attribute },
   { "unused",                 0, 0, false, false, false,
@@ -4448,6 +4451,28 @@
 				tree args ATTRIBUTE_UNUSED,
 				int flags ATTRIBUTE_UNUSED,
 				bool *no_add_attrs)
+{
+  if (TREE_CODE (*node) == FUNCTION_DECL)
+    {
+      /* Do nothing else, just set the attribute.  We'll get at
+	 it later with lookup_attribute.  */
+    }
+  else
+    {
+      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
+/* Handle a "leafify" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_leafify_attribute (tree *node, tree name,
+			  tree args ATTRIBUTE_UNUSED,
+			  int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
 {
   if (TREE_CODE (*node) == FUNCTION_DECL)
     {
Index: cgraph.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cgraph.c,v
retrieving revision 1.34
diff -u -u -r1.34 cgraph.c
--- cgraph.c	22 Oct 2003 19:18:03 -0000	1.34
+++ cgraph.c	30 Oct 2003 14:04:50 -0000
@@ -157,6 +157,7 @@
   struct cgraph_edge *edge2;
 
   edge->inline_call = false;
+  edge->maybe_inline_call = false;
   /* At the moment we don't associate calls with specific CALL_EXPRs
      as we probably ought to, so we must preserve inline_call flags to
      be the same in all copies of the same edge.  */
@@ -165,6 +166,7 @@
       if (edge2->callee == callee)
 	{
 	  edge->inline_call = edge2->inline_call;
+	  edge->maybe_inline_call = edge2->maybe_inline_call;
 	  break;
 	}
 
Index: cgraph.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cgraph.h,v
retrieving revision 1.23
diff -u -u -r1.23 cgraph.h
--- cgraph.h	22 Oct 2003 11:58:09 -0000	1.23
+++ cgraph.h	30 Oct 2003 14:04:50 -0000
@@ -120,6 +120,7 @@
   struct cgraph_edge *next_caller;
   struct cgraph_edge *next_callee;
   bool inline_call;
+  bool maybe_inline_call;
 };
 
 /* The cgraph_varpool data strutcture.
Index: cgraphunit.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cgraphunit.c,v
retrieving revision 1.37
diff -u -u -r1.37 cgraphunit.c
--- cgraphunit.c	22 Oct 2003 11:58:09 -0000	1.37
+++ cgraphunit.c	30 Oct 2003 14:04:51 -0000
@@ -57,6 +57,9 @@
 static int initial_insns;
 static int overall_insns;
 
+/* Flag if we expand a leafify function.  */
+static int leafify;
+
 /* Records tree nodes seen in cgraph_create_edges.  Simply using
    walk_tree_without_duplicates doesn't guarantee each node is visited
    once because it gets a new htab upon each recursive call from
@@ -471,7 +474,10 @@
   /* optimize_inline_calls avoids inlining of current_function_decl.  */
   current_function_decl = decl;
   if (flag_inline_trees)
-    optimize_inline_calls (decl);
+    {
+      leafify = (lookup_attribute ("leafify", DECL_ATTRIBUTES (node->decl)) != NULL);
+      optimize_inline_calls (decl);
+    }
   if (node->nested)
     {
       for (node = node->nested; node; node = node->next_nested)
@@ -507,7 +513,7 @@
   else
     {
       for (e = node->callers; e; e = e->next_caller)
-	if (e->inline_call)
+	if (e->inline_call || e->maybe_inline_call)
 	  break;
       if (!e)
 	DECL_SAVED_TREE (decl) = NULL;
@@ -1070,6 +1076,23 @@
   free (heap_node);
 }
 
+/* Go down the call tree marking nodes disregarding inlining limits.  Called
+ * for function decls with attribute((leafify)) set.  */
+
+static void
+cgraph_decide_inlining_leafify(struct cgraph_node *node)
+{
+  struct cgraph_edge *e;
+  if (node->aux)
+    return;
+  for (e = node->callees; e; e = e->next_callee)
+    {
+      e->maybe_inline_call = 1;
+      cgraph_decide_inlining_leafify(e->callee);
+    }
+  node->aux = node;
+}
+
 /* Decide on the inlining.  We do so in the topological order to avoid
    expenses on updating datastructures.  */
 
@@ -1216,6 +1239,28 @@
 	}
     }
 
+  /* For all nodes with their function decl having attribute((leafify)) set
+   * remove inline mark and set maybe_inline_call downward all callees.
+   * Use node->aux to avoid duplicate walking of callees.  */
+
+  for (node = cgraph_nodes; node; node = node->next)
+    node->aux = 0;
+
+  for (i = nnodes - 1; i >= 0; i--)
+    {
+      struct cgraph_edge *e;
+
+      node = order[i];
+
+      if (lookup_attribute ("leafify", DECL_ATTRIBUTES (node->decl)) == NULL)
+        continue;
+
+      for (e = node->callers; e; e = e->next_caller)
+        e->inline_call = 0;
+
+      cgraph_decide_inlining_leafify(node);
+    }
+
   if (cgraph_dump_file)
     fprintf (cgraph_dump_file,
 	     "\nInlined %i calls, eliminated %i functions, "
@@ -1291,7 +1336,8 @@
 
   for (e = caller->callees; e; e = e->next_callee)
     if (e->callee == callee)
-      return e->inline_call;
+      return e->inline_call
+             || (e->maybe_inline_call && leafify);
   /* We do not record builtins in the callgraph.  Perhaps it would make more
      sense to do so and then prune out those not overwritten by explicit
      function body.  */
Index: doc/extend.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/extend.texi,v
retrieving revision 1.169
diff -u -u -r1.169 extend.texi
--- doc/extend.texi	26 Oct 2003 19:03:42 -0000	1.169
+++ doc/extend.texi	30 Oct 2003 14:05:01 -0000
@@ -1976,7 +1976,7 @@
 attributes when making a declaration.  This keyword is followed by an
 attribute specification inside double parentheses.  The following
 attributes are currently defined for functions on all targets:
-@code{noreturn}, @code{noinline}, @code{always_inline},
+@code{noreturn}, @code{noinline}, @code{always_inline}, @code{leafify},
 @code{pure}, @code{const}, @code{nothrow},
 @code{format}, @code{format_arg}, @code{no_instrument_function},
 @code{section}, @code{constructor}, @code{destructor}, @code{used},
@@ -2052,6 +2052,14 @@
 Generally, functions are not inlined unless optimization is specified.
 For functions declared inline, this attribute inlines the function even
 if no optimization level was specified.
+
+@cindex @code{leafify} function attribute
+@item leafify
+Generally, inlining into a function is limited. For a function marked with
+this attribute, every call inside this function will be inlined, if possible.
+This attribute implies that the function itself is not considered for automatic
+inlining, even into functions marked @code{leafify}. So this is the same
+as marking the function @code{noinline} as well.
 
 @cindex @code{pure} function attribute
 @item pure


More information about the Gcc mailing list