OSDN Git Service

2005-07-15 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 15 Jul 2005 09:31:39 +0000 (09:31 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 15 Jul 2005 09:31:39 +0000 (09:31 +0000)
* c-common.c (handle_flatten_attribute): New function.
Add flatten function attribute.
* doc/extend.texi: Document flatten function attribute.
* Makefile.in (ipa-inline.o): Depend on hashtab.h.
* ipa-inline.c (cgraph_find_cycles, cgraph_flatten_node):
New functions.
(cgraph_decide_inlining): Handle functions with flatten
attribute.

* gcc.dg/tree-ssa/flatten-1.c: New testcase.
* gcc.dg/tree-ssa/flatten-2.c: Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@102051 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/Makefile.in
gcc/c-common.c
gcc/doc/extend.texi
gcc/ipa-inline.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/flatten-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/flatten-2.c [new file with mode: 0644]

index 68dec8a..317e2d7 100644 (file)
@@ -1,3 +1,14 @@
+2005-07-15  Richard Guenther  <rguenther@suse.de>
+
+       * c-common.c (handle_flatten_attribute): New function.
+       Add flatten function attribute.
+       * doc/extend.texi: Document flatten function attribute.
+       * Makefile.in (ipa-inline.o): Depend on hashtab.h.
+       * ipa-inline.c (cgraph_find_cycles, cgraph_flatten_node):
+       New functions.
+       (cgraph_decide_inlining): Handle functions with flatten
+       attribute.
+
 2005-07-14  David Edelsohn  <edelsohn@gnu.org>
 
        * config/rs6000/rs6000.md (UNSPEC_SYNC, UNSPEC_LWSYNC,
index 2bc1092..3d8b8bc 100644 (file)
@@ -2141,7 +2141,7 @@ ipa.o : ipa.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(CGRAPH_H)
 ipa-inline.o : ipa-inline.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
    $(TREE_H) langhooks.h tree-inline.h $(FLAGS_H) $(CGRAPH_H) intl.h \
    $(DIAGNOSTIC_H) $(FIBHEAP_H) $(PARAMS_H) $(TIMEVAR_H) tree-pass.h \
-   $(COVERAGE_H)
+   $(COVERAGE_H) $(HASHTAB_H)
 coverage.o : coverage.c $(GCOV_IO_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h \
    $(TM_H) $(RTL_H) $(TREE_H) $(FLAGS_H) output.h $(REGS_H) $(EXPR_H) \
    function.h toplev.h $(GGC_H) langhooks.h $(COVERAGE_H) gt-coverage.h \
index f3d4a28..f7463e1 100644 (file)
@@ -505,6 +505,7 @@ static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
 static tree handle_noinline_attribute (tree *, tree, tree, int, bool *);
 static tree handle_always_inline_attribute (tree *, tree, tree, int,
                                            bool *);
+static tree handle_flatten_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_externally_visible_attribute (tree *, tree, tree, int,
@@ -571,6 +572,8 @@ const struct attribute_spec c_common_attribute_table[] =
                              handle_noinline_attribute },
   { "always_inline",          0, 0, true,  false, false,
                              handle_always_inline_attribute },
+  { "flatten",                0, 0, true,  false, false,
+                              handle_flatten_attribute },
   { "used",                   0, 0, true,  false, false,
                              handle_used_attribute },
   { "unused",                 0, 0, false, false, false,
@@ -4151,6 +4154,28 @@ handle_always_inline_attribute (tree *node, tree name,
   return NULL_TREE;
 }
 
+/* Handle a "flatten" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_flatten_attribute (tree *node, tree name,
+                          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 (OPT_Wattributes, "%qE attribute ignored", name);
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
+
 /* Handle a "used" attribute; arguments as in
    struct attribute_spec.handler.  */
 
index cc6ea2d..f71c520 100644 (file)
@@ -1523,7 +1523,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{returns_twice}, @code{noinline}, @code{always_inline},
-@code{pure}, @code{const}, @code{nothrow}, @code{sentinel},
+@code{flatten}, @code{pure}, @code{const}, @code{nothrow}, @code{sentinel},
 @code{format}, @code{format_arg}, @code{no_instrument_function},
 @code{section}, @code{constructor}, @code{destructor}, @code{used},
 @code{unused}, @code{deprecated}, @code{weak}, @code{malloc},
@@ -1566,6 +1566,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{flatten} function attribute
+@item flatten
+Generally, inlining into a function is limited.  For a function marked with
+this attribute, every call inside this function will be inlined, if possible.
+Whether the function itself is considered for inlining depends on its size and
+the current inlining parameters.  The @code{flatten} attribute only works
+reliably in unit-at-a-time mode.
+
 @item cdecl
 @cindex functions that do pop the argument stack on the 386
 @opindex mrtd
index cb71047..df57ccc 100644 (file)
@@ -78,6 +78,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "fibheap.h"
 #include "intl.h"
 #include "tree-pass.h"
+#include "hashtab.h"
 #include "coverage.h"
 #include "ggc.h"
 
@@ -438,6 +439,65 @@ lookup_recursive_calls (struct cgraph_node *node, struct cgraph_node *where,
       lookup_recursive_calls (node, e->callee, heap);
 }
 
+/* Find callgraph nodes closing a circle in the graph.  The
+   resulting hashtab can be used to avoid walking the circles.
+   Uses the cgraph nodes ->aux field which needs to be zero
+   before and will be zero after operation.  */
+
+static void
+cgraph_find_cycles (struct cgraph_node *node, htab_t cycles)
+{
+  struct cgraph_edge *e;
+
+  if (node->aux)
+    {
+      void **slot;
+      slot = htab_find_slot (cycles, node, INSERT);
+      if (!*slot)
+       {
+         if (dump_file)
+           fprintf (dump_file, "Cycle contains %s\n", cgraph_node_name (node));
+         *slot = node;
+       }
+      return;
+    }
+
+  node->aux = node;
+  for (e = node->callees; e; e = e->next_callee)
+    cgraph_find_cycles (e->callee, cycles); 
+  node->aux = 0;
+}
+
+/* Leafify the cgraph node.  We have to be careful in recursing
+   as to not run endlessly in circles of the callgraph.
+   We do so by using a hashtab of cycle entering nodes as generated
+   by cgraph_find_cycles.  */
+
+static void
+cgraph_flatten_node (struct cgraph_node *node, htab_t cycles)
+{
+  struct cgraph_edge *e;
+
+  for (e = node->callees; e; e = e->next_callee)
+    {
+      /* Inline call, if possible, and recurse.  Be sure we are not
+        entering callgraph circles here.  */
+      if (e->inline_failed
+         && e->callee->local.inlinable
+         && !cgraph_recursive_inlining_p (node, e->callee,
+                                          &e->inline_failed)
+         && !htab_find (cycles, e->callee))
+       {
+         if (dump_file)
+           fprintf (dump_file, " inlining %s", cgraph_node_name (e->callee));
+          cgraph_mark_inline_edge (e);
+         cgraph_flatten_node (e->callee, cycles);
+       }
+      else if (dump_file)
+       fprintf (dump_file, " !inlining %s", cgraph_node_name (e->callee));
+    }
+}
+
 /* Decide on recursive inlining: in the case function has recursive calls,
    inline until body size reaches given argument.  */
 
@@ -769,6 +829,24 @@ cgraph_decide_inlining (void)
 
       node = order[i];
 
+      /* Handle nodes to be flattened, but don't update overall unit size.  */
+      if (lookup_attribute ("flatten", DECL_ATTRIBUTES (node->decl)) != NULL)
+        {
+         int old_overall_insns = overall_insns;
+         htab_t cycles;
+         if (dump_file)
+           fprintf (dump_file,
+                    "Leafifying %s\n", cgraph_node_name (node));
+         cycles = htab_create (7, htab_hash_pointer, htab_eq_pointer, NULL);
+         cgraph_find_cycles (node, cycles);
+         cgraph_flatten_node (node, cycles);
+         htab_delete (cycles);
+         overall_insns = old_overall_insns;
+         /* We don't need to consider always_inline functions inside the flattened
+            function anymore.  */
+         continue;
+        }
+
       if (!node->local.disregard_inline_limits)
        continue;
       if (dump_file)
index 2e5eee9..6bef685 100644 (file)
@@ -1,3 +1,8 @@
+2005-07-15  Richard Guenther  <rguenther@suse.de>
+
+       * gcc.dg/tree-ssa/flatten-1.c: New testcase.
+       * gcc.dg/tree-ssa/flatten-2.c: Likewise.
+
 2005-07-15  Steven Bosscher  <stevenb@suse.de>
 
        PR tree-optimization/22230
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/flatten-1.c b/gcc/testsuite/gcc.dg/tree-ssa/flatten-1.c
new file mode 100644 (file)
index 0000000..4561f75
--- /dev/null
@@ -0,0 +1,57 @@
+/* { dg-do compile } */
+/* { dg-options -O2 } */
+
+/* Basic tests for flatten attribute, check we end up
+   with only the flattened function bodies.  */
+
+static int foobar(int i);
+static int bar(int i);
+
+int __attribute__((flatten)) leaf0a(int i)
+{
+  return bar(i);
+}
+int __attribute__((flatten)) leaf0b(int i)
+{
+  return foobar(i);
+}
+int __attribute__((flatten)) leaf1(int i)
+{
+  return bar(foobar(i));
+}
+int __attribute__((flatten)) leaf2(int i)
+{
+  int j;
+  j = foobar(i);
+  return bar(j);
+}
+
+static int foobar(int i)
+{
+  return i-1;
+}
+static int bar(int i)
+{
+  return i + foobar(i);
+}
+
+
+static int g(int i)
+{
+  return i*5+1;
+}
+static int f(int i)
+{
+  return g(i);
+}
+int __attribute__((flatten)) leaf3(int i)
+{
+  int j;
+  j = f(i);
+  j += f(i);
+  return j;
+}
+
+/* { dg-final { scan-assembler-not "g:" } } */
+/* { dg-final { scan-assembler-not "f:" } } */
+/* { dg-final { scan-assembler-not "bar:" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/flatten-2.c b/gcc/testsuite/gcc.dg/tree-ssa/flatten-2.c
new file mode 100644 (file)
index 0000000..56e8083
--- /dev/null
@@ -0,0 +1,76 @@
+/* { dg-do compile } */
+/* { dg-options -O2 } */
+
+/* Check that we finish compiling even if instructed to
+   flatten a cyclic callgraph.  Verify we correctly
+   flatten with another function marked flatten in the
+   callgraph.  */
+
+void __attribute__((flatten)) direct(void)
+{
+  direct();
+}
+
+
+void __attribute__((flatten)) indirect(void);
+static void indirect1(void)
+{
+  indirect();
+}
+void __attribute__((flatten)) indirect(void)
+{
+  indirect1();
+}
+
+
+void __attribute__((flatten)) doubleindirect(void);
+static void doubleindirect2(void)
+{
+  doubleindirect();
+}
+static void doubleindirect1(void)
+{
+  doubleindirect2();
+}
+void __attribute__((flatten)) doubleindirect(void)
+{
+  doubleindirect1();
+}
+
+
+static void subcycle1(void);
+static void subcycle2(void)
+{
+  subcycle1();
+}
+static void subcycle1(void)
+{
+  subcycle2();
+}
+void __attribute__((flatten)) subcycle(void)
+{
+  subcycle1();
+}
+
+
+static void doublesubcycle1(void);
+static void doublesubcycle2(void);
+static void doublesubcycle3(void)
+{
+  doublesubcycle1();
+}
+static void doublesubcycle2(void)
+{
+  doublesubcycle3();
+}
+static void doublesubcycle1(void)
+{
+  doublesubcycle2();
+}
+void __attribute__((flatten)) doublesubcycle(void)
+{
+  doublesubcycle1();
+}
+
+/* { dg-final { scan-assembler "cycle.:" } } */
+/* { dg-final { scan-assembler-not "indirect.:" } } */