aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAlexandre Oliva <aoliva@redhat.com>2001-10-05 02:48:47 +0000
committerAlexandre Oliva <aoliva@gcc.gnu.org>2001-10-05 02:48:47 +0000
commit25af8512559873d4b6e67d27a07f504a585b6037 (patch)
tree8512628500ca03ba513e5684fba6a6a044156017 /gcc
parentffb0e73a97aacc285d5cb176af65359b3329739b (diff)
downloadgcc-25af8512559873d4b6e67d27a07f504a585b6037.zip
gcc-25af8512559873d4b6e67d27a07f504a585b6037.tar.gz
gcc-25af8512559873d4b6e67d27a07f504a585b6037.tar.bz2
Make-lang.in (cp/decl.o, cp/tree.o): Depend on tree-inline.h.
* Make-lang.in (cp/decl.o, cp/tree.o): Depend on tree-inline.h. (cp/pt.o, cp/semantics.o, cp/optimize.o): Likewise. * cp-tree.h (lang_decl): Moved inlined_fns to tree_decl. (TREE_READONLY_DECL_P, DECL_INLINED_FNS): Moved to ../tree.h. (flag_inline_trees): Moved declaration to ../tree-inline.h. (walk_tree): Moved declaration to ../tree-inline.h. (walk_tree_without_duplicates, copy_tree_r): Likewise. (remap_save_expr): Likewise. * decl.c: Include tree-inline.h. (lang_mark_tree): Don't mark inlined_fns. * decl2.c (flag_inline_trees): Moved defn to ../tree-inline.c. * optimize.c: Include tree-inline.h. (optimize_inline_calls): Move declaration to ../tree.h, as non-static. (remap_decl): Use language-independent constructs and hooks. (remap_block, copy_body_r, declare_return_variable): Likewise. (inlinable_function_p): Likewise. Don't test for DECL_LANG_SPECIFIC before DECL_INLINED_FNS as inlined_fns is no longer language-specific. (optimize_inline_calls): Likewise. Make it non-static. Moved call of dump_function to... (optimize_function): Here... (clone_body): New function, extracted from... (maybe_clone_body): ... here. Build decl_map locally and pass it on to clone_body. * pt.c, semantics.c: Include tree-inline.h. * tree.c: Likewise. (cp_walk_subtrees): New language-specific hook for tree inlining. (cp_cannot_inline_tree_fn, cp_add_pending_fn_decls, cp_is_overload_p, cp_auto_var_in_fn_p, cp_copy_res_decl_for_inlining): Likewise. (walk_tree): Move language-specific constructs into... (cp_walk_subtrees): this new function. (copy_tree_r): Use language-independent constructs and hooks. (init_tree): Initialize tree inlining hooks. (remap_save_expr): Adjust prototype so that the declaration does not require the definition of splay_tree. From-SVN: r46020
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog40
-rw-r--r--gcc/cp/Make-lang.in11
-rw-r--r--gcc/cp/cp-tree.h28
-rw-r--r--gcc/cp/decl.c2
-rw-r--r--gcc/cp/decl2.c7
-rw-r--r--gcc/cp/optimize.c213
-rw-r--r--gcc/cp/pt.c2
-rw-r--r--gcc/cp/semantics.c1
-rw-r--r--gcc/cp/tree.c271
9 files changed, 385 insertions, 190 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index c23768e..2926e12 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,43 @@
+2001-10-04 Alexandre Oliva <aoliva@redhat.com>
+
+ * Make-lang.in (cp/decl.o, cp/tree.o): Depend on tree-inline.h.
+ (cp/pt.o, cp/semantics.o, cp/optimize.o): Likewise.
+ * cp-tree.h (lang_decl): Moved inlined_fns to tree_decl.
+ (TREE_READONLY_DECL_P, DECL_INLINED_FNS): Moved to ../tree.h.
+ (flag_inline_trees): Moved declaration to ../tree-inline.h.
+ (walk_tree): Moved declaration to ../tree-inline.h.
+ (walk_tree_without_duplicates, copy_tree_r): Likewise.
+ (remap_save_expr): Likewise.
+ * decl.c: Include tree-inline.h.
+ (lang_mark_tree): Don't mark inlined_fns.
+ * decl2.c (flag_inline_trees): Moved defn to ../tree-inline.c.
+ * optimize.c: Include tree-inline.h.
+ (optimize_inline_calls): Move declaration to ../tree.h, as
+ non-static.
+ (remap_decl): Use language-independent constructs and hooks.
+ (remap_block, copy_body_r, declare_return_variable): Likewise.
+ (inlinable_function_p): Likewise. Don't test for
+ DECL_LANG_SPECIFIC before DECL_INLINED_FNS as inlined_fns is
+ no longer language-specific.
+ (optimize_inline_calls): Likewise. Make it non-static. Moved
+ call of dump_function to...
+ (optimize_function): Here...
+ (clone_body): New function, extracted from...
+ (maybe_clone_body): ... here. Build decl_map locally and pass
+ it on to clone_body.
+ * pt.c, semantics.c: Include tree-inline.h.
+ * tree.c: Likewise.
+ (cp_walk_subtrees): New language-specific hook for tree inlining.
+ (cp_cannot_inline_tree_fn, cp_add_pending_fn_decls,
+ cp_is_overload_p, cp_auto_var_in_fn_p,
+ cp_copy_res_decl_for_inlining): Likewise.
+ (walk_tree): Move language-specific constructs into...
+ (cp_walk_subtrees): this new function.
+ (copy_tree_r): Use language-independent constructs and hooks.
+ (init_tree): Initialize tree inlining hooks.
+ (remap_save_expr): Adjust prototype so that the declaration
+ does not require the definition of splay_tree.
+
2001-10-03 John David Anglin <dave@hiauly1.hia.nrc.ca>
* rtti.c (get_tinfo_decl): Call typeinfo_in_lib_p with the type used
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index 4fe7e87..65a1606 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -243,7 +243,7 @@ cp/lex.o: cp/lex.c $(CXX_TREE_H) cp/parse.h flags.h cp/lex.h c-pragma.h \
$(TM_P_H)
cp/decl.o: cp/decl.c $(CXX_TREE_H) flags.h cp/lex.h cp/decl.h stack.h \
output.h $(EXPR_H) except.h toplev.h hash.h $(GGC_H) $(RTL_H) \
- cp/operators.def $(TM_P_H)
+ cp/operators.def $(TM_P_H) tree-inline.h
cp/decl2.o: cp/decl2.c $(CXX_TREE_H) flags.h cp/lex.h cp/decl.h $(EXPR_H) \
output.h except.h toplev.h $(GGC_H) $(RTL_H)
cp/typeck2.o: cp/typeck2.c $(CXX_TREE_H) flags.h toplev.h output.h $(TM_P_H) \
@@ -261,7 +261,7 @@ cp/method.o: cp/method.c $(CXX_TREE_H) toplev.h $(GGC_H) $(RTL_H) $(EXPR_H) \
cp/cvt.o: cp/cvt.c $(CXX_TREE_H) cp/decl.h flags.h toplev.h convert.h
cp/search.o: cp/search.c $(CXX_TREE_H) stack.h flags.h toplev.h $(RTL_H)
cp/tree.o: cp/tree.c $(CXX_TREE_H) flags.h toplev.h $(GGC_H) $(RTL_H) \
- insn-config.h integrate.h
+ insn-config.h integrate.h tree-inline.h
cp/ptree.o: cp/ptree.c $(CXX_TREE_H) $(SYSTEM_H)
cp/rtti.o: cp/rtti.c $(CXX_TREE_H) flags.h toplev.h
cp/except.o: cp/except.c $(CXX_TREE_H) flags.h $(RTL_H) except.h toplev.h \
@@ -270,14 +270,15 @@ cp/expr.o: cp/expr.c $(CXX_TREE_H) $(RTL_H) flags.h $(EXPR_H) toplev.h \
except.h $(TM_P_H)
cp/xref.o: cp/xref.c $(CXX_TREE_H) input.h toplev.h
cp/pt.o: cp/pt.c $(CXX_TREE_H) cp/decl.h cp/parse.h cp/lex.h toplev.h \
- $(GGC_H) $(RTL_H) except.h
+ $(GGC_H) $(RTL_H) except.h tree-inline.h
cp/error.o: cp/error.c $(CXX_TREE_H) toplev.h diagnostic.h flags.h real.h
cp/repo.o: cp/repo.c $(CXX_TREE_H) toplev.h $(GGC_H) diagnostic.h
cp/semantics.o: cp/semantics.c $(CXX_TREE_H) cp/lex.h except.h toplev.h \
- flags.h $(GGC_H) debug.h output.h $(RTL_H) $(TIMEVAR_H) $(EXPR_H)
+ flags.h $(GGC_H) debug.h output.h $(RTL_H) $(TIMEVAR_H) $(EXPR_H) \
+ tree-inline.h
cp/dump.o: cp/dump.c $(CXX_TREE_H) c-dump.h
cp/optimize.o: cp/optimize.c $(CXX_TREE_H) rtl.h integrate.h insn-config.h \
- input.h $(PARAMS_H) debug.h
+ input.h $(PARAMS_H) debug.h tree-inline.h
cp/mangle.o: cp/mangle.c $(CXX_TREE_H) toplev.h
cp/parse.o: cp/parse.c $(CXX_TREE_H) flags.h cp/lex.h except.h output.h \
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index b4fc016..98e747d 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1758,10 +1758,6 @@ struct lang_decl
/* In a FUNCTION_DECL, this is DECL_CLONED_FUNCTION. */
tree cloned_function;
- /* In a FUNCTION_DECL, these are function data which is to be kept
- as long as FUNCTION_DECL is kept. */
- tree inlined_fns;
-
union
{
tree sorted_fields;
@@ -1778,10 +1774,6 @@ struct lang_decl
#define DEFARG_POINTER(NODE) (DEFAULT_ARG_CHECK(NODE)->identifier.id.str)
-/* Non-zero if NODE is a _DECL with TREE_READONLY set. */
-#define TREE_READONLY_DECL_P(NODE) \
- (TREE_READONLY (NODE) && DECL_P (NODE))
-
/* DECL_NEEDED_P holds of a declaration when we need to emit its
definition. This is true when the back-end tells us that
the symbol has been referenced in the generated code. If, however,
@@ -1888,10 +1880,6 @@ 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)
-
/* Nonzero if NODE has DECL_DISCRIMINATOR and not DECL_ACCESS. */
#define DECL_DISCRIMINATOR_P(NODE) \
(TREE_CODE (NODE) == VAR_DECL \
@@ -3262,13 +3250,6 @@ extern int flag_implicit_templates;
extern int flag_weak;
-/* 0 if we should not perform inlining.
- 1 if we should expand functions calls inline at the tree level.
- 2 if we should consider *all* functions to be inline
- candidates. */
-
-extern int flag_inline_trees;
-
/* Nonzero if we're done parsing and into end-of-file activities. */
extern int at_eof;
@@ -4197,18 +4178,9 @@ extern void debug_binfo PARAMS ((tree));
extern tree build_dummy_object PARAMS ((tree));
extern tree maybe_dummy_object PARAMS ((tree, tree *));
extern int is_dummy_object PARAMS ((tree));
-extern tree walk_tree PARAMS ((tree *,
- walk_tree_fn,
- void *,
- htab_t));
-extern tree walk_tree_without_duplicates PARAMS ((tree *,
- walk_tree_fn,
- void *));
-extern tree copy_tree_r PARAMS ((tree *, int *, void *));
extern const struct attribute_spec cp_attribute_table[];
extern tree make_ptrmem_cst PARAMS ((tree, tree));
extern tree cp_build_qualified_type_real PARAMS ((tree, int, int));
-extern void remap_save_expr PARAMS ((tree *, splay_tree, tree, int *));
#define cp_build_qualified_type(TYPE, QUALS) \
cp_build_qualified_type_real ((TYPE), (QUALS), /*complain=*/1)
extern tree build_shared_int_cst PARAMS ((int));
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 905784e..0dfd8d6 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -35,6 +35,7 @@ Boston, MA 02111-1307, USA. */
#include "expr.h"
#include "flags.h"
#include "cp-tree.h"
+#include "tree-inline.h"
#include "decl.h"
#include "lex.h"
#include "output.h"
@@ -14479,7 +14480,6 @@ lang_mark_tree (t)
ggc_mark_tree (ld->befriending_classes);
ggc_mark_tree (ld->context);
ggc_mark_tree (ld->cloned_function);
- ggc_mark_tree (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/decl2.c b/gcc/cp/decl2.c
index ee8f379..0ab9299 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -378,13 +378,6 @@ int flag_weak = 1;
int flag_use_cxa_atexit;
-/* 0 if we should not perform inlining.
- 1 if we should expand functions calls inline at the tree level.
- 2 if we should consider *all* functions to be inline
- candidates. */
-
-int flag_inline_trees = 0;
-
/* Maximum template instantiation depth. This limit is rather
arbitrary, but it exists to limit the time it takes to notice
infinite template instantiations. */
diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c
index 95d02b7..bbc555b 100644
--- a/gcc/cp/optimize.c
+++ b/gcc/cp/optimize.c
@@ -33,6 +33,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "params.h"
#include "hashtab.h"
#include "debug.h"
+#include "tree-inline.h"
/* To Do:
@@ -99,7 +100,6 @@ static int inlinable_function_p PARAMS ((tree, inline_data *));
static tree remap_decl PARAMS ((tree, inline_data *));
static void remap_block PARAMS ((tree, tree, inline_data *));
static void copy_scope_stmt PARAMS ((tree *, int *, inline_data *));
-static void optimize_inline_calls PARAMS ((tree));
static tree calls_setjmp_r PARAMS ((tree *, int *, void *));
static void update_cloned_parm PARAMS ((tree, tree));
static void dump_function PARAMS ((enum tree_dump_index, tree));
@@ -121,7 +121,7 @@ remap_decl (decl, id)
/* We only remap local variables in the current function. */
fn = VARRAY_TOP_TREE (id->fns);
- if (!nonstatic_local_decl_p (decl) || DECL_CONTEXT (decl) != fn)
+ if (! LANG_AUTO_VAR_IN_FN_P (decl, fn))
return NULL_TREE;
/* See if we have remapped this declaration. */
@@ -151,8 +151,8 @@ remap_decl (decl, id)
copy_body_r, id, NULL);
}
- if (!DECL_NAME (t) && TREE_TYPE (t)
- && ANON_AGGR_TYPE_P (TREE_TYPE ((t))))
+ if (! DECL_NAME (t) && TREE_TYPE (t)
+ && LANG_ANON_AGGR_TYPE_P (TREE_TYPE (t)))
{
/* For a VAR_DECL of anonymous type, we must also copy the
member VAR_DECLS here and rechain the
@@ -165,7 +165,8 @@ remap_decl (decl, id)
{
tree member = remap_decl (TREE_VALUE (src), id);
- my_friendly_assert (!TREE_PURPOSE (src), 20010529);
+ if (TREE_PURPOSE (src))
+ abort ();
members = tree_cons (NULL, member, members);
}
DECL_ANON_UNION_ELEMS (t) = nreverse (members);
@@ -277,7 +278,8 @@ remap_block (scope_stmt, decls, id)
/* Find this block in the table of remapped things. */
n = splay_tree_lookup (id->decl_map,
(splay_tree_key) SCOPE_STMT_BLOCK (scope_stmt));
- my_friendly_assert (n != NULL, 19991203);
+ if (! n)
+ abort ();
SCOPE_STMT_BLOCK (scope_stmt) = (tree) n->value;
}
}
@@ -322,12 +324,14 @@ copy_body_r (tp, walk_subtrees, data)
id = (inline_data *) data;
fn = VARRAY_TOP_TREE (id->fns);
+#if 0
/* All automatic variables should have a DECL_CONTEXT indicating
what function they come from. */
if ((TREE_CODE (*tp) == VAR_DECL || TREE_CODE (*tp) == LABEL_DECL)
&& DECL_NAMESPACE_SCOPE_P (*tp))
- my_friendly_assert (DECL_EXTERNAL (*tp) || TREE_STATIC (*tp),
- 19991113);
+ if (! DECL_EXTERNAL (*tp) && ! TREE_STATIC (*tp))
+ abort ();
+#endif
/* If this is a RETURN_STMT, change it into an EXPR_STMT and a
GOTO_STMT with the RET_LABEL as its target. */
@@ -359,26 +363,29 @@ copy_body_r (tp, walk_subtrees, data)
variables. We don't want to copy static variables; there's only
one of those, no matter how many times we inline the containing
function. */
- else if (nonstatic_local_decl_p (*tp) && DECL_CONTEXT (*tp) == fn)
+ else if (LANG_AUTO_VAR_IN_FN_P (*tp, fn))
{
tree new_decl;
/* Remap the declaration. */
new_decl = remap_decl (*tp, id);
- my_friendly_assert (new_decl != NULL_TREE, 19991203);
+ if (! new_decl)
+ abort ();
/* Replace this variable with the copy. */
STRIP_TYPE_NOPS (new_decl);
*tp = new_decl;
}
+#if 0
else if (nonstatic_local_decl_p (*tp)
&& DECL_CONTEXT (*tp) != VARRAY_TREE (id->fns, 0))
- my_friendly_abort (0);
+ abort ();
+#endif
else if (TREE_CODE (*tp) == SAVE_EXPR)
remap_save_expr (tp, id->decl_map, VARRAY_TREE (id->fns, 0),
walk_subtrees);
else if (TREE_CODE (*tp) == UNSAVE_EXPR)
/* UNSAVE_EXPRs should not be generated until expansion time. */
- my_friendly_abort (19991113);
+ abort ();
/* For a SCOPE_STMT, we must copy the associated block so that we
can write out debugging information for the inlined variables. */
else if (TREE_CODE (*tp) == SCOPE_STMT && !id->in_target_cleanup_p)
@@ -398,8 +405,7 @@ copy_body_r (tp, walk_subtrees, data)
}
else if (TREE_CODE (*tp) == MODIFY_EXPR
&& TREE_OPERAND (*tp, 0) == TREE_OPERAND (*tp, 1)
- && nonstatic_local_decl_p (TREE_OPERAND (*tp, 0))
- && DECL_CONTEXT (TREE_OPERAND (*tp, 0)) == fn)
+ && LANG_AUTO_VAR_IN_FN_P (TREE_OPERAND (*tp, 0), fn))
{
/* Some assignments VAR = VAR; don't generate any rtl code
and thus don't count as variable modification. Avoid
@@ -561,7 +567,7 @@ declare_return_variable (id, use_stmt)
tree fn = VARRAY_TOP_TREE (id->fns);
tree result = DECL_RESULT (fn);
tree var;
- int aggregate_return_p;
+ int need_return_decl = 1;
/* We don't need to do anything for functions that don't return
anything. */
@@ -571,29 +577,9 @@ declare_return_variable (id, use_stmt)
return NULL_TREE;
}
- /* Figure out whether or not FN returns an aggregate. */
- aggregate_return_p = IS_AGGR_TYPE (TREE_TYPE (result));
-
- /* If FN returns an aggregate then the caller will always create the
- temporary (using a TARGET_EXPR) and the call will be the
- initializing expression for the TARGET_EXPR. If we were just to
- create a new VAR_DECL here, then the result of this function
- would be copied (bitwise) into the variable initialized by the
- TARGET_EXPR. That's incorrect, so we must transform any
- references to the RESULT into references to the target. */
- if (aggregate_return_p)
- {
- my_friendly_assert (VARRAY_ACTIVE_SIZE (id->target_exprs) != 0,
- 20000430);
- var = TREE_OPERAND (VARRAY_TOP_TREE (id->target_exprs), 0);
- my_friendly_assert
- (same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (var),
- TREE_TYPE (result)),
- 20000430);
- }
- /* Otherwise, make an appropriate copy. */
- else
- var = copy_decl_for_inlining (result, fn, VARRAY_TREE (id->fns, 0));
+ var = LANG_COPY_RES_DECL_FOR_INLINING (result, fn, VARRAY_TREE (id->fns, 0),
+ id->decl_map, &need_return_decl,
+ &id->target_exprs);
/* Register the VAR_DECL as the equivalent for the RESULT_DECL; that
way, when the RESULT_DECL is encountered, it will be
@@ -602,29 +588,12 @@ declare_return_variable (id, use_stmt)
(splay_tree_key) result,
(splay_tree_value) var);
- if (DECL_SAVED_FUNCTION_DATA (fn))
- {
- tree nrv = DECL_SAVED_FUNCTION_DATA (fn)->x_return_value;
- if (nrv)
- {
- /* We have a named return value; copy the name and source
- position so we can get reasonable debugging information, and
- register the return variable as its equivalent. */
- DECL_NAME (var) = DECL_NAME (nrv);
- DECL_SOURCE_FILE (var) = DECL_SOURCE_FILE (nrv);
- DECL_SOURCE_LINE (var) = DECL_SOURCE_LINE (nrv);
- splay_tree_insert (id->decl_map,
- (splay_tree_key) nrv,
- (splay_tree_value) var);
- }
- }
-
/* Build the USE_STMT. */
*use_stmt = build_stmt (EXPR_STMT, var);
/* Build the declaration statement if FN does not return an
aggregate. */
- if (!aggregate_return_p)
+ if (need_return_decl)
return build_stmt (DECL_STMT, var);
/* If FN does return an aggregate, there's no need to declare the
return variable; we're using a variable in our caller's frame. */
@@ -656,12 +625,11 @@ inlinable_function_p (fn, id)
it. */
else if (!DECL_INLINE (fn))
;
- /* We can't inline varargs functions. */
- else if (varargs_function_p (fn))
- ;
- /* We can't inline functions that are too big.
- * Only allow a single function to eat up half of our budget. */
- else if (DECL_NUM_STMTS (fn) * INSNS_PER_STMT > MAX_INLINE_INSNS / 2)
+ /* We can't inline functions that are too big. Only allow a single
+ function to eat up half of our budget. Make special allowance
+ for extern inline functions, though. */
+ else if (! LANG_DISREGARD_INLINE_LIMITS (fn)
+ && DECL_NUM_STMTS (fn) * INSNS_PER_STMT > MAX_INLINE_INSNS / 2)
;
/* All is well. We can inline this function. Traditionally, GCC
has refused to inline functions using alloca, or functions whose
@@ -675,27 +643,26 @@ inlinable_function_p (fn, id)
/* Even if this function is not itself too big to inline, it might
be that we've done so much inlining already that we don't want to
- risk too much inlining any more and thus halve the acceptable size. */
- if ((DECL_NUM_STMTS (fn) + id->inlined_stmts) * INSNS_PER_STMT
- > MAX_INLINE_INSNS
+ risk too much inlining any more and thus halve the acceptable
+ size. */
+ if (! LANG_DISREGARD_INLINE_LIMITS (fn)
+ && ((DECL_NUM_STMTS (fn) + id->inlined_stmts) * INSNS_PER_STMT
+ > MAX_INLINE_INSNS)
&& DECL_NUM_STMTS (fn) * INSNS_PER_STMT > MAX_INLINE_INSNS / 4)
inlinable = 0;
- /* We can inline a template instantiation only if it's fully
- instantiated. */
- if (inlinable
- && DECL_TEMPLATE_INFO (fn)
- && TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (fn)))
- {
- fn = instantiate_decl (fn, /*defer_ok=*/0);
- inlinable = !TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (fn));
- }
-
+ if (inlinable && LANG_CANNOT_INLINE_TREE_FN (&fn))
+ inlinable = 0;
+
/* If we don't have the function body available, we can't inline
it. */
if (!DECL_SAVED_TREE (fn))
inlinable = 0;
+ /* Check again, language hooks may have modified it. */
+ if (! inlinable || DECL_UNINLINABLE (fn))
+ return 0;
+
/* Don't do recursive inlining, either. We don't record this in
DECL_UNINLINABLE; we may be able to inline this function later. */
if (inlinable)
@@ -706,7 +673,7 @@ inlinable_function_p (fn, id)
if (VARRAY_TREE (id->fns, i) == fn)
return 0;
- if (inlinable && DECL_LANG_SPECIFIC (fn) && DECL_INLINED_FNS (fn))
+ if (inlinable && DECL_INLINED_FNS (fn))
{
int j;
tree inlined_fns = DECL_INLINED_FNS (fn);
@@ -808,7 +775,7 @@ expand_call_inline (tp, walk_subtrees, data)
for the return statements within the function to jump to. The
type of the statement expression is the return type of the
function call. */
- expr = build_min (STMT_EXPR, TREE_TYPE (TREE_TYPE (fn)), NULL_TREE);
+ expr = build1 (STMT_EXPR, TREE_TYPE (TREE_TYPE (fn)), NULL_TREE);
/* Local declarations will be replaced by their equivalents in this
map. */
@@ -832,7 +799,7 @@ expand_call_inline (tp, walk_subtrees, data)
/* 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))
+ if (! DECL_INLINED_FNS (fn))
{
int i;
@@ -878,9 +845,9 @@ expand_call_inline (tp, walk_subtrees, data)
/* Close the block for the parameters. */
scope_stmt = build_stmt (SCOPE_STMT, DECL_INITIAL (fn));
SCOPE_NO_CLEANUPS_P (scope_stmt) = 1;
- my_friendly_assert (DECL_INITIAL (fn)
- && TREE_CODE (DECL_INITIAL (fn)) == BLOCK,
- 19991203);
+ if (! DECL_INITIAL (fn)
+ || TREE_CODE (DECL_INITIAL (fn)) != BLOCK)
+ abort ();
remap_block (scope_stmt, NULL_TREE, id);
STMT_EXPR_STMT (expr)
= chainon (STMT_EXPR_STMT (expr), scope_stmt);
@@ -957,13 +924,12 @@ expand_calls_inline (tp, id)
/* Expand calls to inline functions in the body of FN. */
-static void
+void
optimize_inline_calls (fn)
tree fn;
{
inline_data id;
tree prev_fn;
- struct saved_scope *s;
/* Clear out ID. */
memset (&id, 0, sizeof (id));
@@ -978,12 +944,8 @@ optimize_inline_calls (fn)
VARRAY_PUSH_TREE (id.fns, current_function_decl);
prev_fn = current_function_decl;
}
- for (s = scope_chain; s; s = s->prev)
- if (s->function_decl && s->function_decl != prev_fn)
- {
- VARRAY_PUSH_TREE (id.fns, s->function_decl);
- prev_fn = s->function_decl;
- }
+
+ prev_fn = LANG_ADD_PENDING_FN_DECLS (&id.fns, prev_fn);
/* Create the stack of TARGET_EXPRs. */
VARRAY_TREE_INIT (id.target_exprs, 32, "target_exprs");
@@ -1014,8 +976,6 @@ optimize_inline_calls (fn)
DECL_INLINED_FNS (fn) = ifn;
}
VARRAY_FREE (id.inlined_fns);
-
- dump_function (TDI_inlined, fn);
}
/* Optimize the body of FN. */
@@ -1043,7 +1003,11 @@ optimize_function (fn)
optimization, (c) virtual functions are rarely inlineable,
and (d) ASM_OUTPUT_MI_THUNK is there to DTRT anyway. */
&& !DECL_THUNK_P (fn))
- optimize_inline_calls (fn);
+ {
+ optimize_inline_calls (fn);
+
+ dump_function (TDI_inlined, fn);
+ }
/* Undo the call to ggc_push_context above. */
--function_depth;
@@ -1106,6 +1070,38 @@ update_cloned_parm (parm, cloned_parm)
DECL_SOURCE_LINE (cloned_parm) = DECL_SOURCE_LINE (parm);
}
+/* FN is a function that has a complete body, and CLONE is a function
+ whose body is to be set to a copy of FN, mapping argument
+ declarations according to the ARG_MAP splay_tree. */
+
+void
+clone_body (clone, fn, arg_map)
+ tree clone, fn;
+ void *arg_map;
+{
+ inline_data id;
+
+ /* Clone the body, as if we were making an inline call. But, remap
+ the parameters in the callee to the parameters of caller. If
+ there's an in-charge parameter, map it to an appropriate
+ constant. */
+ memset (&id, 0, sizeof (id));
+ VARRAY_TREE_INIT (id.fns, 2, "fns");
+ VARRAY_PUSH_TREE (id.fns, clone);
+ VARRAY_PUSH_TREE (id.fns, fn);
+ id.decl_map = (splay_tree)arg_map;
+
+ /* Cloning is treated slightly differently from inlining. Set
+ CLONING_P so that it's clear which operation we're performing. */
+ id.cloning_p = true;
+
+ /* Actually copy the body. */
+ TREE_CHAIN (DECL_SAVED_TREE (clone)) = copy_body (&id);
+
+ /* Clean up. */
+ VARRAY_FREE (id.fns);
+}
+
/* FN is a function that has a complete body. Clone the body as
necessary. Returns non-zero if there's no longer any need to
process the main body. */
@@ -1114,7 +1110,6 @@ int
maybe_clone_body (fn)
tree fn;
{
- inline_data id;
tree clone;
int first = 1;
@@ -1135,6 +1130,7 @@ maybe_clone_body (fn)
tree parm;
tree clone_parm;
int parmno;
+ splay_tree decl_map;
/* Update CLONE's source position information to match FN's. */
DECL_SOURCE_FILE (clone) = DECL_SOURCE_FILE (fn);
@@ -1178,22 +1174,8 @@ maybe_clone_body (fn)
push_to_top_level ();
start_function (NULL_TREE, clone, NULL_TREE, SF_PRE_PARSED);
- /* Just clone the body, as if we were making an inline call.
- But, remap the parameters in the callee to the parameters of
- caller. If there's an in-charge parameter, map it to an
- appropriate constant. */
- memset (&id, 0, sizeof (id));
- VARRAY_TREE_INIT (id.fns, 2, "fns");
- VARRAY_PUSH_TREE (id.fns, clone);
- VARRAY_PUSH_TREE (id.fns, fn);
-
- /* Cloning is treated slightly differently from inlining. Set
- CLONING_P so that its clear which operation we're performing. */
- id.cloning_p = true;
-
/* Remap the parameters. */
- id.decl_map = splay_tree_new (splay_tree_compare_pointers,
- NULL, NULL);
+ decl_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
for (parmno = 0,
parm = DECL_ARGUMENTS (fn),
clone_parm = DECL_ARGUMENTS (clone);
@@ -1206,7 +1188,7 @@ maybe_clone_body (fn)
{
tree in_charge;
in_charge = in_charge_arg_for_name (DECL_NAME (clone));
- splay_tree_insert (id.decl_map,
+ splay_tree_insert (decl_map,
(splay_tree_key) parm,
(splay_tree_value) in_charge);
}
@@ -1219,7 +1201,7 @@ maybe_clone_body (fn)
if (DECL_HAS_VTT_PARM_P (clone))
{
DECL_ABSTRACT_ORIGIN (clone_parm) = parm;
- splay_tree_insert (id.decl_map,
+ splay_tree_insert (decl_map,
(splay_tree_key) parm,
(splay_tree_value) clone_parm);
clone_parm = TREE_CHAIN (clone_parm);
@@ -1227,7 +1209,7 @@ maybe_clone_body (fn)
/* Otherwise, map the VTT parameter to `NULL'. */
else
{
- splay_tree_insert (id.decl_map,
+ splay_tree_insert (decl_map,
(splay_tree_key) parm,
(splay_tree_value) null_pointer_node);
}
@@ -1236,23 +1218,22 @@ maybe_clone_body (fn)
function. */
else
{
- splay_tree_insert (id.decl_map,
+ splay_tree_insert (decl_map,
(splay_tree_key) parm,
(splay_tree_value) clone_parm);
clone_parm = TREE_CHAIN (clone_parm);
}
}
- /* Actually copy the body. */
- TREE_CHAIN (DECL_SAVED_TREE (clone)) = copy_body (&id);
+ /* Clone the body. */
+ clone_body (clone, fn, decl_map);
/* There are as many statements in the clone as in the
original. */
DECL_NUM_STMTS (clone) = DECL_NUM_STMTS (fn);
/* Clean up. */
- splay_tree_delete (id.decl_map);
- VARRAY_FREE (id.fns);
+ splay_tree_delete (decl_map);
/* Now, expand this function into RTL, if appropriate. */
finish_function (0);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 292513f..e29a738 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -29,10 +29,10 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
#include "obstack.h"
-
#include "tree.h"
#include "flags.h"
#include "cp-tree.h"
+#include "tree-inline.h"
#include "decl.h"
#include "parse.h"
#include "lex.h"
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 6564f8e..ec7b968 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -28,6 +28,7 @@
#include "system.h"
#include "tree.h"
#include "cp-tree.h"
+#include "tree-inline.h"
#include "except.h"
#include "lex.h"
#include "toplev.h"
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 32783ad..ec51eaa 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -31,6 +31,7 @@ Boston, MA 02111-1307, USA. */
#include "ggc.h"
#include "insn-config.h"
#include "integrate.h"
+#include "tree-inline.h"
static tree bot_manip PARAMS ((tree *, int *, void *));
static tree bot_replace PARAMS ((tree *, int *, void *));
@@ -49,6 +50,12 @@ static tree count_trees_r PARAMS ((tree *, int *, void *));
static tree verify_stmt_tree_r PARAMS ((tree *, int *, void *));
static tree find_tree_r PARAMS ((tree *, int *, void *));
extern int cp_statement_code_p PARAMS ((enum tree_code));
+static treeopt_walk_subtrees_type cp_walk_subtrees;
+static treeopt_cannot_inline_tree_fn_type cp_cannot_inline_tree_fn;
+static treeopt_add_pending_fn_decls_type cp_add_pending_fn_decls;
+static treeopt_tree_chain_matters_p_type cp_is_overload_p;
+static treeopt_auto_var_in_fn_p_type cp_auto_var_in_fn_p;
+static treeopt_copy_res_decl_for_inlining_type cp_copy_res_decl_for_inlining;
static tree handle_java_interface_attribute PARAMS ((tree *, tree, tree, int, bool *));
static tree handle_com_interface_attribute PARAMS ((tree *, tree, tree, int, bool *));
@@ -1154,12 +1161,13 @@ bind_template_template_parm (t, newargs)
once. */
tree
-walk_tree (tp, func, data, htab)
+walk_tree (tp, func, data, htab_)
tree *tp;
walk_tree_fn func;
void *data;
- htab_t htab;
+ void *htab_;
{
+ htab_t htab = (htab_t) htab_;
enum tree_code code;
int walk_subtrees;
tree result;
@@ -1204,7 +1212,8 @@ walk_tree (tp, func, data, htab)
interesting below this point in the tree. */
if (!walk_subtrees)
{
- if (statement_code_p (code) || code == TREE_LIST || code == OVERLOAD)
+ if (statement_code_p (code) || code == TREE_LIST
+ || LANG_TREE_CHAIN_MATTERS_P (*tp))
/* But we still need to check our siblings. */
return walk_tree (&TREE_CHAIN (*tp), func, data, htab);
else
@@ -1268,6 +1277,10 @@ walk_tree (tp, func, data, htab)
return NULL_TREE;
}
+ result = LANG_WALK_SUBTREES (tp, &walk_subtrees, func, data, htab);
+ if (result || ! walk_subtrees)
+ return result;
+
/* Not one of the easy cases. We must explicitly go through the
children. */
switch (code)
@@ -1277,47 +1290,29 @@ walk_tree (tp, func, data, htab)
case INTEGER_CST:
case REAL_CST:
case STRING_CST:
- case DEFAULT_ARG:
- case TEMPLATE_TEMPLATE_PARM:
- case BOUND_TEMPLATE_TEMPLATE_PARM:
- case TEMPLATE_PARM_INDEX:
- case TEMPLATE_TYPE_PARM:
case REAL_TYPE:
case COMPLEX_TYPE:
case VECTOR_TYPE:
case VOID_TYPE:
case BOOLEAN_TYPE:
- case TYPENAME_TYPE:
case UNION_TYPE:
case ENUMERAL_TYPE:
- case TYPEOF_TYPE:
case BLOCK:
+ case RECORD_TYPE:
/* None of thse have subtrees other than those already walked
above. */
break;
- case PTRMEM_CST:
- WALK_SUBTREE (TREE_TYPE (*tp));
- break;
-
case POINTER_TYPE:
case REFERENCE_TYPE:
WALK_SUBTREE (TREE_TYPE (*tp));
break;
case TREE_LIST:
- /* A BASELINK_P's TREE_PURPOSE is a BINFO, and hence circular. */
- if (!BASELINK_P (*tp))
- WALK_SUBTREE (TREE_PURPOSE (*tp));
WALK_SUBTREE (TREE_VALUE (*tp));
WALK_SUBTREE (TREE_CHAIN (*tp));
break;
- case OVERLOAD:
- WALK_SUBTREE (OVL_FUNCTION (*tp));
- WALK_SUBTREE (OVL_CHAIN (*tp));
- break;
-
case TREE_VEC:
{
int len = TREE_VEC_LENGTH (*tp);
@@ -1365,13 +1360,8 @@ walk_tree (tp, func, data, htab)
WALK_SUBTREE (TYPE_OFFSET_BASETYPE (*tp));
break;
- case RECORD_TYPE:
- if (TYPE_PTRMEMFUNC_P (*tp))
- WALK_SUBTREE (TYPE_PTRMEMFUNC_FN_TYPE (*tp));
- break;
-
default:
- my_friendly_abort (19990803);
+ abort ();
}
/* We didn't find what we were looking for. */
@@ -1539,7 +1529,7 @@ copy_tree_r (tp, walk_subtrees, data)
|| TREE_CODE_CLASS (code) == 's'
|| code == TREE_LIST
|| code == TREE_VEC
- || code == OVERLOAD)
+ || LANG_TREE_CHAIN_MATTERS_P (*tp))
{
/* Because the chain gets clobbered when we make a copy, we save it
here. */
@@ -1550,7 +1540,8 @@ copy_tree_r (tp, walk_subtrees, data)
/* Now, restore the chain, if appropriate. That will cause
walk_tree to walk into the chain as well. */
- if (code == PARM_DECL || code == TREE_LIST || code == OVERLOAD
+ if (code == PARM_DECL || code == TREE_LIST
+ || LANG_TREE_CHAIN_MATTERS_P (*tp)
|| statement_code_p (code))
TREE_CHAIN (*tp) = chain;
@@ -2344,12 +2335,227 @@ make_ptrmem_cst (type, member)
return ptrmem_cst;
}
+/* Apply FUNC to all language-specific sub-trees of TP in a pre-order
+ traversal. Called from walk_tree(). */
+
+static tree
+cp_walk_subtrees (tp, walk_subtrees_p, func, data, htab)
+ tree *tp;
+ int *walk_subtrees_p;
+ walk_tree_fn func;
+ void *data;
+ void *htab;
+{
+ enum tree_code code = TREE_CODE (*tp);
+ tree result;
+
+#define WALK_SUBTREE(NODE) \
+ do \
+ { \
+ result = walk_tree (&(NODE), func, data, htab); \
+ if (result) \
+ return result; \
+ } \
+ while (0)
+
+ /* Not one of the easy cases. We must explicitly go through the
+ children. */
+ switch (code)
+ {
+ case DEFAULT_ARG:
+ case TEMPLATE_TEMPLATE_PARM:
+ case BOUND_TEMPLATE_TEMPLATE_PARM:
+ case TEMPLATE_PARM_INDEX:
+ case TEMPLATE_TYPE_PARM:
+ case TYPENAME_TYPE:
+ case TYPEOF_TYPE:
+ /* None of thse have subtrees other than those already walked
+ above. */
+ *walk_subtrees_p = 0;
+ break;
+
+ case PTRMEM_CST:
+ WALK_SUBTREE (TREE_TYPE (*tp));
+ *walk_subtrees_p = 0;
+ break;
+
+ case TREE_LIST:
+ /* A BASELINK_P's TREE_PURPOSE is a BINFO, and hence circular. */
+ if (!BASELINK_P (*tp))
+ WALK_SUBTREE (TREE_PURPOSE (*tp));
+ break;
+
+ case OVERLOAD:
+ WALK_SUBTREE (OVL_FUNCTION (*tp));
+ WALK_SUBTREE (OVL_CHAIN (*tp));
+ *walk_subtrees_p = 0;
+ break;
+
+ case RECORD_TYPE:
+ if (TYPE_PTRMEMFUNC_P (*tp))
+ WALK_SUBTREE (TYPE_PTRMEMFUNC_FN_TYPE (*tp));
+ break;
+
+ default:
+ break;
+ }
+
+ /* We didn't find what we were looking for. */
+ return NULL_TREE;
+
+#undef WALK_SUBTREE
+}
+
+/* Decide whether there are language-specific reasons to not inline a
+ function as a tree. */
+
+static int
+cp_cannot_inline_tree_fn (fnp)
+ tree *fnp;
+{
+ tree fn = *fnp;
+
+ /* We can inline a template instantiation only if it's fully
+ instantiated. */
+ if (DECL_TEMPLATE_INFO (fn)
+ && TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (fn)))
+ {
+ fn = *fnp = instantiate_decl (fn, /*defer_ok=*/0);
+ return TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (fn));
+ }
+
+ if (varargs_function_p (fn))
+ {
+ DECL_UNINLINABLE (fn) = 1;
+ return 1;
+ }
+
+ if (! function_attribute_inlinable_p (fn))
+ {
+ DECL_UNINLINABLE (fn) = 1;
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Add any pending functions other than the current function (already
+ handled by the caller), that thus cannot be inlined, to FNS_P, then
+ return the latest function added to the array, PREV_FN. */
+
+static tree
+cp_add_pending_fn_decls (fns_p, prev_fn)
+ void *fns_p;
+ tree prev_fn;
+{
+ varray_type *fnsp = (varray_type *)fns_p;
+ struct saved_scope *s;
+
+ for (s = scope_chain; s; s = s->prev)
+ if (s->function_decl && s->function_decl != prev_fn)
+ {
+ VARRAY_PUSH_TREE (*fnsp, s->function_decl);
+ prev_fn = s->function_decl;
+ }
+
+ return prev_fn;
+}
+
+/* Determine whether a tree node is an OVERLOAD node. Used to decide
+ whether to copy a node or to preserve its chain when inlining a
+ function. */
+
+static int
+cp_is_overload_p (t)
+ tree t;
+{
+ return TREE_CODE (t) == OVERLOAD;
+}
+
+/* Determine whether VAR is a declaration of an automatic variable in
+ function FN. */
+
+static int
+cp_auto_var_in_fn_p (var, fn)
+ tree var, fn;
+{
+ return (DECL_P (var) && DECL_CONTEXT (var) == fn
+ && nonstatic_local_decl_p (var));
+}
+
+/* Tell whether a declaration is needed for the RESULT of a function
+ FN being inlined into CALLER or if the top node of target_exprs is
+ to be used. */
+
+static tree
+cp_copy_res_decl_for_inlining (result, fn, caller, decl_map_,
+ need_decl, target_exprs)
+ tree result, fn, caller;
+ void *decl_map_;
+ int *need_decl;
+ void *target_exprs;
+{
+ splay_tree decl_map = (splay_tree)decl_map_;
+ varray_type *texps = (varray_type *)target_exprs;
+ tree var;
+ int aggregate_return_p;
+
+ /* Figure out whether or not FN returns an aggregate. */
+ aggregate_return_p = IS_AGGR_TYPE (TREE_TYPE (result));
+ *need_decl = ! aggregate_return_p;
+
+ /* If FN returns an aggregate then the caller will always create the
+ temporary (using a TARGET_EXPR) and the call will be the
+ initializing expression for the TARGET_EXPR. If we were just to
+ create a new VAR_DECL here, then the result of this function
+ would be copied (bitwise) into the variable initialized by the
+ TARGET_EXPR. That's incorrect, so we must transform any
+ references to the RESULT into references to the target. */
+ if (aggregate_return_p)
+ {
+ if (VARRAY_ACTIVE_SIZE (*texps) == 0)
+ abort ();
+ var = TREE_OPERAND (VARRAY_TOP_TREE (*texps), 0);
+ if (! same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (var),
+ TREE_TYPE (result)))
+ abort ();
+ }
+ /* Otherwise, make an appropriate copy. */
+ else
+ var = copy_decl_for_inlining (result, fn, caller);
+
+ if (DECL_SAVED_FUNCTION_DATA (fn))
+ {
+ tree nrv = DECL_SAVED_FUNCTION_DATA (fn)->x_return_value;
+ if (nrv)
+ {
+ /* We have a named return value; copy the name and source
+ position so we can get reasonable debugging information, and
+ register the return variable as its equivalent. */
+ DECL_NAME (var) = DECL_NAME (nrv);
+ DECL_SOURCE_FILE (var) = DECL_SOURCE_FILE (nrv);
+ DECL_SOURCE_LINE (var) = DECL_SOURCE_LINE (nrv);
+ splay_tree_insert (decl_map,
+ (splay_tree_key) nrv,
+ (splay_tree_value) var);
+ }
+ }
+
+ return var;
+}
+
/* Initialize tree.c. */
void
init_tree ()
{
make_lang_type_fn = cp_make_lang_type;
+ lang_walk_subtrees = cp_walk_subtrees;
+ lang_cannot_inline_tree_fn = cp_cannot_inline_tree_fn;
+ lang_add_pending_fn_decls = cp_add_pending_fn_decls;
+ lang_tree_chain_matters_p = cp_is_overload_p;
+ lang_auto_var_in_fn_p = cp_auto_var_in_fn_p;
+ lang_copy_res_decl_for_inlining = cp_copy_res_decl_for_inlining;
lang_unsave = cp_unsave;
lang_statement_code_p = cp_statement_code_p;
lang_set_decl_assembler_name = mangle_decl;
@@ -2365,12 +2571,13 @@ init_tree ()
ST. FN is the function into which the copy will be placed. */
void
-remap_save_expr (tp, st, fn, walk_subtrees)
+remap_save_expr (tp, st_, fn, walk_subtrees)
tree *tp;
- splay_tree st;
+ void *st_;
tree fn;
int *walk_subtrees;
{
+ splay_tree st = (splay_tree) st_;
splay_tree_node n;
/* See if we already encountered this SAVE_EXPR. */