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