aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2001-02-22 12:46:33 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2001-02-22 12:46:33 +0100
commitb3bae5e2bf8b2f06d687adb32740f6258b5e3b36 (patch)
treeca3614007d0819a932a044965511b4b6c9fbc586 /gcc
parent35723595ab2119465335b36a7fc599a96c91d461 (diff)
downloadgcc-b3bae5e2bf8b2f06d687adb32740f6258b5e3b36.zip
gcc-b3bae5e2bf8b2f06d687adb32740f6258b5e3b36.tar.gz
gcc-b3bae5e2bf8b2f06d687adb32740f6258b5e3b36.tar.bz2
cp-tree.h (struct lang_decl_inlined_fns): New.
* cp-tree.h (struct lang_decl_inlined_fns): New. (struct lang_decls): Add inlined_fns. (DECL_INLINED_FNS): New macro. * optimize.c (struct inline_data): Add inlined_fns. (declare_return_variable): Use VARRAY_ACTIVE_SIZE macro. (inlinable_function_p): Likewise, fix typo in comment, function is not inlinable if it already inlined function currently being optimized. (expand_call_inline): Add fn to inlined_fns if neccessary. (optimize_function): Initialize inlined_fns. Save inlined_fns into DECL_INLINED_FNS after expanding inlines. * decl.c (mark_inlined_fns): New function. (lang_mark_tree): Call it. * g++.old-deja/g++.other/inline20.C: New test. From-SVN: r39977
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog16
-rw-r--r--gcc/cp/cp-tree.h13
-rw-r--r--gcc/cp/decl.c15
-rw-r--r--gcc/cp/optimize.c49
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/inline20.C58
6 files changed, 151 insertions, 4 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 9c0ad71..5686f48 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,19 @@
+2001-02-22 Jakub Jelinek <jakub@redhat.com>
+
+ * cp-tree.h (struct lang_decl_inlined_fns): New.
+ (struct lang_decls): Add inlined_fns.
+ (DECL_INLINED_FNS): New macro.
+ * optimize.c (struct inline_data): Add inlined_fns.
+ (declare_return_variable): Use VARRAY_ACTIVE_SIZE macro.
+ (inlinable_function_p): Likewise, fix typo in comment,
+ function is not inlinable if it already inlined function currently
+ being optimized.
+ (expand_call_inline): Add fn to inlined_fns if neccessary.
+ (optimize_function): Initialize inlined_fns.
+ Save inlined_fns into DECL_INLINED_FNS after expanding inlines.
+ * decl.c (mark_inlined_fns): New function.
+ (lang_mark_tree): Call it.
+
2001-02-21 Jason Merrill <jason@redhat.com>
* cp-tree.h (struct lang_decl_flags): Remove uninlinable flag.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 240832a..2aca7d1 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1855,6 +1855,12 @@ struct lang_decl_flags
struct unparsed_text;
+struct lang_decl_inlined_fns
+{
+ size_t num_fns;
+ tree fns[1];
+};
+
struct lang_decl
{
struct lang_decl_flags decl_flags;
@@ -1868,6 +1874,9 @@ struct lang_decl
/* In a FUNCTION_DECL, this is DECL_CLONED_FUNCTION. */
tree cloned_function;
+ /* In a FUNCTION_DECL, this is a list of trees inlined into its body. */
+ struct lang_decl_inlined_fns *inlined_fns;
+
union
{
tree sorted_fields;
@@ -1978,6 +1987,10 @@ struct lang_decl
#define DECL_CLONED_FUNCTION(NODE) \
(DECL_LANG_SPECIFIC (NODE)->cloned_function)
+/* List of FUNCION_DECLs inlined into this function's body. */
+#define DECL_INLINED_FNS(NODE) \
+ (DECL_LANG_SPECIFIC (NODE)->inlined_fns)
+
/* Non-zero if the VTT parm has been added to NODE. */
#define DECL_HAS_VTT_PARM_P(NODE) \
(DECL_LANG_SPECIFIC (NODE)->decl_flags.has_vtt_parm_p)
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 85e9fa6..3900895 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -14332,6 +14332,19 @@ pop_cp_function_context (f)
f->language = 0;
}
+/* Mark I for GC. */
+
+static void
+mark_inlined_fns (i)
+ struct lang_decl_inlined_fns *i;
+{
+ int n;
+
+ for (n = i->num_fns - 1; n >= 0; n--)
+ ggc_mark_tree (i->fns [n]);
+ ggc_set_mark (i);
+}
+
/* Mark P for GC. */
static void
@@ -14418,6 +14431,8 @@ lang_mark_tree (t)
ggc_mark_tree (ld->befriending_classes);
ggc_mark_tree (ld->context);
ggc_mark_tree (ld->cloned_function);
+ if (ld->inlined_fns)
+ mark_inlined_fns (ld->inlined_fns);
if (TREE_CODE (t) == TYPE_DECL)
ggc_mark_tree (ld->u.sorted_fields);
else if (TREE_CODE (t) == FUNCTION_DECL
diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c
index 21c94ea..9850c6f 100644
--- a/gcc/cp/optimize.c
+++ b/gcc/cp/optimize.c
@@ -28,6 +28,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "input.h"
#include "integrate.h"
#include "varray.h"
+#include "ggc.h"
/* To Do:
@@ -62,6 +63,8 @@ typedef struct inline_data
int in_target_cleanup_p;
/* A stack of the TARGET_EXPRs that we are currently processing. */
varray_type target_exprs;
+ /* A list of the functions current function has inlined. */
+ varray_type inlined_fns;
} inline_data;
/* Prototypes. */
@@ -520,7 +523,7 @@ declare_return_variable (id, use_stmt)
references to the RESULT into references to the target. */
if (aggregate_return_p)
{
- my_friendly_assert (id->target_exprs->elements_used != 0,
+ my_friendly_assert (VARRAY_ACTIVE_SIZE (id->target_exprs) != 0,
20000430);
var = TREE_OPERAND (VARRAY_TOP_TREE (id->target_exprs), 0);
my_friendly_assert
@@ -605,14 +608,23 @@ inlinable_function_p (fn, id)
inlinable = 0;
/* Don't do recursive inlining, either. We don't record this in
- DECL_UNLINABLE; we may be able to inline this function later. */
+ DECL_UNINLINABLE; we may be able to inline this function later. */
if (inlinable)
{
size_t i;
- for (i = 0; i < id->fns->elements_used; ++i)
+ for (i = 0; i < VARRAY_ACTIVE_SIZE (id->fns); ++i)
if (VARRAY_TREE (id->fns, i) == fn)
- inlinable = 0;
+ return 0;
+
+ if (inlinable && DECL_LANG_SPECIFIC (fn) && DECL_INLINED_FNS (fn))
+ {
+ struct lang_decl_inlined_fns *ifn = DECL_INLINED_FNS (fn);
+
+ for (i = 0; i < ifn->num_fns; ++i)
+ if (ifn->fns [i] == VARRAY_TREE (id->fns, 0))
+ return 0;
+ }
}
/* Return the result. */
@@ -728,6 +740,19 @@ expand_call_inline (tp, walk_subtrees, data)
recursing into it. */
VARRAY_PUSH_TREE (id->fns, fn);
+ /* Record the function we are about to inline if optimize_function
+ has not been called on it yet and we don't have it in the list. */
+ if (DECL_LANG_SPECIFIC (fn) && !DECL_INLINED_FNS (fn))
+ {
+ int i;
+
+ for (i = VARRAY_ACTIVE_SIZE (id->inlined_fns) - 1; i >= 0; i--)
+ if (VARRAY_TREE (id->inlined_fns, i) == fn)
+ break;
+ if (i < 0)
+ VARRAY_PUSH_TREE (id->inlined_fns, fn);
+ }
+
/* Return statements in the function body will be replaced by jumps
to the RET_LABEL. */
id->ret_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
@@ -874,6 +899,9 @@ optimize_function (fn)
/* Create the stack of TARGET_EXPRs. */
VARRAY_TREE_INIT (id.target_exprs, 32, "target_exprs");
+ /* Create the list of functions this call will inline. */
+ VARRAY_TREE_INIT (id.inlined_fns, 32, "inlined_fns");
+
/* Replace all calls to inline functions with the bodies of those
functions. */
expand_calls_inline (&DECL_SAVED_TREE (fn), &id);
@@ -881,6 +909,19 @@ optimize_function (fn)
/* Clean up. */
VARRAY_FREE (id.fns);
VARRAY_FREE (id.target_exprs);
+ if (DECL_LANG_SPECIFIC (fn))
+ {
+ struct lang_decl_inlined_fns *ifn;
+
+ ifn = ggc_alloc (sizeof (struct lang_decl_inlined_fns)
+ + (VARRAY_ACTIVE_SIZE (id.inlined_fns) - 1)
+ * sizeof (tree));
+ ifn->num_fns = VARRAY_ACTIVE_SIZE (id.inlined_fns);
+ memcpy (&ifn->fns[0], &VARRAY_TREE (id.inlined_fns, 0),
+ ifn->num_fns * sizeof (tree));
+ DECL_INLINED_FNS (fn) = ifn;
+ }
+ VARRAY_FREE (id.inlined_fns);
}
/* Undo the call to ggc_push_context above. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 682b3a9..a41d374 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2001-02-22 Jakub Jelinek <jakub@redhat.com>
+
+ * g++.old-deja/g++.other/inline20.C: New test.
+
Wed Feb 21 12:38:22 2001 Ovidiu Predescu <ovidiu@cup.hp.com>
* objc/execute/nested-1.m: Added (contributed by Nicola Pero).
diff --git a/gcc/testsuite/g++.old-deja/g++.other/inline20.C b/gcc/testsuite/g++.old-deja/g++.other/inline20.C
new file mode 100644
index 0000000..a4af375
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.other/inline20.C
@@ -0,0 +1,58 @@
+// Build don't link:
+
+struct A {
+ int a, b, c, d;
+};
+
+inline void foo (int, A &);
+
+struct D {
+};
+
+struct E: public D {
+ void f (A &y)
+ {
+ foo (1, y);
+ }
+};
+
+struct F: public D {
+ void f (A &y)
+ {
+ foo (2, y);
+ }
+};
+
+E *d;
+F *e;
+
+inline int baz (int y)
+{
+ A a;
+ if (y) {
+ d->f (a);
+ } else {
+ e->f (a);
+ }
+ return 0;
+}
+
+inline void foo (int y, A &z)
+{
+ z.a = baz (y);
+ z.b = baz (y);
+ z.c = baz (y);
+ z.d = baz (y);
+}
+
+struct G {
+ E a;
+ F b;
+ void bar (A &);
+};
+
+void G::bar(A &y)
+{
+ a.f(y);
+ b.f(y);
+}