From: Jakub Jelinek Date: Thu, 22 Feb 2001 11:46:33 +0000 (+0100) Subject: cp-tree.h (struct lang_decl_inlined_fns): New. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=b3bae5e2bf8b2f06d687adb32740f6258b5e3b36;p=gcc.git 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 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 9c0ad71cae2..5686f48a7f5 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,19 @@ +2001-02-22 Jakub Jelinek + + * 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 * 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 240832a9c71..2aca7d1de1f 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 85e9fa6b178..39008956f4a 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 21c94eafee6..9850c6ff971 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 682b3a973b3..a41d374f5c8 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2001-02-22 Jakub Jelinek + + * g++.old-deja/g++.other/inline20.C: New test. + Wed Feb 21 12:38:22 2001 Ovidiu Predescu * 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 00000000000..a4af375f164 --- /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); +}