This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: RFC: Java inliner
Alexandre Oliva writes:
> On Jul 10, 2002, Andrew Haley <aph@redhat.com> wrote:
>
> >> Hmm, I hadn't got the impression you had relied on the preprocessor to
> >> separate the C/C++-specific bits from the generic/Java ones.
>
> > I had a try, but it was getting rather complex.
>
> I was just thinking of running something like
>
> diff --ifdef=INLINER_FOR_JAVA tree-inline.c java/java-inline.c
>
> and then using the result as the new tree-inline.c
Okay, here it is. Looks like you were right.
Andrew.
2002-07-30 Andrew Haley <aph@redhat.com>
* tree-inline.c: Add includes for Java inliner.
(remap_decl): Don't handle anonymous types for Java.
(remap_block): Add handling for Java trees.
(copy_scope_stmt): Conditionalize for non-Java use only.
(copy_body_r): Handle Java trees. Add handling for
LABELED_BLOCK_EXPR, EXIT_BLOCK_EXPR, Java blocks.
(initialize_inlined_parameters): Handle Java trees.
(declare_return_variable): Likewise.
(expand_call_inline): Handle Java trees.
(walk_tree): Likewise.
(copy_tree_r): Don't handle SCOPE_STMTs for Java.
(add_stmt_to_compound): New function.
2002-07-30 Andrew Haley <aph@redhat.com>
* Make-lang.in (java-tree-inline.o): New.
(JAVA_OBJS): Add java-tree-inline.o.
* parse.y (source_end_java_method): Call java_optimize_inline.
(java_expand_method_bodies): Save method's tree in
DECL_SAVED_TREE.
(add_stmt_to_compound): Keep track of the number of statments.
* lang.c (java_init): Enable flag_inline_trees.
(java_post_options): If flag_inline_functions is on, enable
flag_inline_trees instread.
(decl_constant_value): New.
(java_tree_inlining_walk_subtrees): New.
* java-tree.h (DECL_NUM_STMTS): New macro.
(java_optimize_inline): Declare.
* expr.c (java_expand_expr): Allow a BLOCK to return a value.
Handle a LABEL_EXPR>
* decl.c (build_result_decl): If we already have a DECL_RESULT
don't make another.
(dump_function): New.
(java_optimize_inline): New.
(dump_function): New.
Index: tree-inline.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-inline.c,v
retrieving revision 1.26
diff -p -2 -c -r1.26 tree-inline.c
*** tree-inline.c 13 Jun 2002 15:32:40 -0000 1.26
--- tree-inline.c 30 Jul 2002 12:46:00 -0000
*************** Boston, MA 02111-1307, USA. */
*** 39,43 ****
--- 39,48 ----
/* This should be eventually be generalized to other languages, but
this would require a shared function-as-trees infrastructure. */
+ #ifndef INLINER_FOR_JAVA
#include "c-common.h"
+ #else /* INLINER_FOR_JAVA */
+ #include "parse.h"
+ #include "java-tree.h"
+ #endif /* INLINER_FOR_JAVA */
/* 0 if we should not perform inlining.
*************** typedef struct inline_data
*** 103,107 ****
/* Prototypes. */
- static tree initialize_inlined_parameters PARAMS ((inline_data *, tree, tree));
static tree declare_return_variable PARAMS ((inline_data *, tree *));
static tree copy_body_r PARAMS ((tree *, int *, void *));
--- 108,111 ----
*************** static void expand_calls_inline PARAMS (
*** 111,116 ****
--- 115,127 ----
static int inlinable_function_p PARAMS ((tree, inline_data *));
static tree remap_decl PARAMS ((tree, inline_data *));
+ #ifndef INLINER_FOR_JAVA
+ static tree initialize_inlined_parameters PARAMS ((inline_data *, tree, tree));
static void remap_block PARAMS ((tree, tree, inline_data *));
static void copy_scope_stmt PARAMS ((tree *, int *, inline_data *));
+ #else /* INLINER_FOR_JAVA */
+ static tree initialize_inlined_parameters PARAMS ((inline_data *, tree, tree, tree));
+ static void remap_block PARAMS ((tree *, tree, inline_data *));
+ static tree add_stmt_to_compound PARAMS ((tree, tree, tree));
+ #endif /* INLINER_FOR_JAVA */
/* The approximate number of instructions per statement. This number
*************** remap_decl (decl, id)
*** 159,162 ****
--- 170,174 ----
}
+ #ifndef INLINER_FOR_JAVA
if (! DECL_NAME (t) && TREE_TYPE (t)
&& (*lang_hooks.tree_inlining.anon_aggr_type_p) (TREE_TYPE (t)))
*************** remap_decl (decl, id)
*** 179,182 ****
--- 191,195 ----
DECL_ANON_UNION_ELEMS (t) = nreverse (members);
}
+ #endif /* not INLINER_FOR_JAVA */
/* Remember it, so that if we encounter this local entity
*************** remap_decl (decl, id)
*** 190,204 ****
--- 203,228 ----
}
+ #ifndef INLINER_FOR_JAVA
/* Copy the SCOPE_STMT_BLOCK associated with SCOPE_STMT to contain
remapped versions of the variables therein. And hook the new block
into the block-tree. If non-NULL, the DECLS are declarations to
add to use instead of the BLOCK_VARS in the old block. */
+ #else /* INLINER_FOR_JAVA */
+ /* Copy the BLOCK to contain remapped versions of the variables
+ therein. And hook the new block into the block-tree. */
+ #endif /* INLINER_FOR_JAVA */
static void
+ #ifndef INLINER_FOR_JAVA
remap_block (scope_stmt, decls, id)
tree scope_stmt;
+ #else /* INLINER_FOR_JAVA */
+ remap_block (block, decls, id)
+ tree *block;
+ #endif /* INLINER_FOR_JAVA */
tree decls;
inline_data *id;
{
+ #ifndef INLINER_FOR_JAVA
/* We cannot do this in the cleanup for a TARGET_EXPR since we do
not know whether or not expand_expr will actually write out the
*************** remap_block (scope_stmt, decls, id)
*** 290,295 ****
--- 314,366 ----
SCOPE_STMT_BLOCK (scope_stmt) = (tree) n->value;
}
+ #else /* INLINER_FOR_JAVA */
+ tree old_block;
+ tree new_block;
+ tree old_var;
+ tree fn;
+
+ /* Make the new block. */
+ old_block = *block;
+ new_block = make_node (BLOCK);
+ TREE_USED (new_block) = TREE_USED (old_block);
+ BLOCK_ABSTRACT_ORIGIN (new_block) = old_block;
+ BLOCK_SUBBLOCKS (new_block) = BLOCK_SUBBLOCKS (old_block);
+ TREE_SIDE_EFFECTS (new_block) = TREE_SIDE_EFFECTS (old_block);
+ TREE_TYPE (new_block) = TREE_TYPE (old_block);
+ *block = new_block;
+
+ /* Remap its variables. */
+ for (old_var = decls ? decls : BLOCK_VARS (old_block);
+ old_var;
+ old_var = TREE_CHAIN (old_var))
+ {
+ tree new_var;
+
+ /* Remap the variable. */
+ new_var = remap_decl (old_var, id);
+ /* If we didn't remap this variable, so we can't mess with
+ its TREE_CHAIN. If we remapped this variable to
+ something other than a declaration (say, if we mapped it
+ to a constant), then we must similarly omit any mention
+ of it here. */
+ if (!new_var || !DECL_P (new_var))
+ ;
+ else
+ {
+ TREE_CHAIN (new_var) = BLOCK_VARS (new_block);
+ BLOCK_VARS (new_block) = new_var;
+ }
+ }
+ /* We put the BLOCK_VARS in reverse order; fix that now. */
+ BLOCK_VARS (new_block) = nreverse (BLOCK_VARS (new_block));
+ fn = VARRAY_TREE (id->fns, 0);
+ /* Remember the remapped block. */
+ splay_tree_insert (id->decl_map,
+ (splay_tree_key) old_block,
+ (splay_tree_value) new_block);
+ #endif /* INLINER_FOR_JAVA */
}
+ #ifndef INLINER_FOR_JAVA
/* Copy the SCOPE_STMT pointed to by TP. */
*************** copy_scope_stmt (tp, walk_subtrees, id)
*** 315,322 ****
remap_block (*tp, NULL_TREE, id);
}
/* Called from copy_body via walk_tree. DATA is really an
`inline_data *'. */
-
static tree
copy_body_r (tp, walk_subtrees, data)
--- 386,393 ----
remap_block (*tp, NULL_TREE, id);
}
+ #endif /* not INLINER_FOR_JAVA */
/* Called from copy_body via walk_tree. DATA is really an
`inline_data *'. */
static tree
copy_body_r (tp, walk_subtrees, data)
*************** copy_body_r (tp, walk_subtrees, data)
*** 341,347 ****
--- 412,427 ----
#endif
+ #ifdef INLINER_FOR_JAVA
+ if (TREE_CODE (*tp) == BLOCK)
+ remap_block (tp, NULL_TREE, id);
+ #endif
+
/* If this is a RETURN_STMT, change it into an EXPR_STMT and a
GOTO_STMT with the RET_LABEL as its target. */
+ #ifndef INLINER_FOR_JAVA
if (TREE_CODE (*tp) == RETURN_STMT && id->ret_label)
+ #else /* INLINER_FOR_JAVA */
+ if (TREE_CODE (*tp) == RETURN_EXPR && id->ret_label)
+ #endif /* INLINER_FOR_JAVA */
{
tree return_stmt = *tp;
*************** copy_body_r (tp, walk_subtrees, data)
*** 349,359 ****
--- 429,445 ----
/* Build the GOTO_STMT. */
+ #ifndef INLINER_FOR_JAVA
goto_stmt = build_stmt (GOTO_STMT, id->ret_label);
TREE_CHAIN (goto_stmt) = TREE_CHAIN (return_stmt);
GOTO_FAKE_P (goto_stmt) = 1;
+ #else /* INLINER_FOR_JAVA */
+ goto_stmt = build1 (GOTO_EXPR, void_type_node, id->ret_label);
+ TREE_SIDE_EFFECTS (goto_stmt) = 1;
+ #endif /* INLINER_FOR_JAVA */
/* If we're returning something, just turn that into an
assignment into the equivalent of the original
RESULT_DECL. */
+ #ifndef INLINER_FOR_JAVA
if (RETURN_EXPR (return_stmt))
{
*************** copy_body_r (tp, walk_subtrees, data)
*** 364,367 ****
--- 450,462 ----
TREE_CHAIN (*tp) = goto_stmt;
}
+ #else /* INLINER_FOR_JAVA */
+ tree assignment = TREE_OPERAND (return_stmt, 0);
+ if (assignment)
+ {
+ copy_body_r (&assignment, walk_subtrees, data);
+ *tp = build (COMPOUND_EXPR, void_type_node, assignment, goto_stmt);
+ TREE_SIDE_EFFECTS (*tp) = 1;
+ }
+ #endif /* INLINER_FOR_JAVA */
/* If we're not returning anything just do the jump. */
else
*************** copy_body_r (tp, walk_subtrees, data)
*** 395,402 ****
--- 490,522 ----
/* UNSAVE_EXPRs should not be generated until expansion time. */
abort ();
+ #ifndef INLINER_FOR_JAVA
/* 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)
copy_scope_stmt (tp, walk_subtrees, id);
+ #else /* INLINER_FOR_JAVA */
+ else if (TREE_CODE (*tp) == LABELED_BLOCK_EXPR)
+ {
+ /* We need a new copy of this labeled block; the EXIT_BLOCK_EXPR
+ will refer to it, so save a copy ready for remapping. We
+ save it in the decl_map, although it isn't a decl. */
+ tree new_block = copy_node (*tp);
+ splay_tree_insert (id->decl_map,
+ (splay_tree_key) *tp,
+ (splay_tree_value) new_block);
+ *tp = new_block;
+ }
+ else if (TREE_CODE (*tp) == EXIT_BLOCK_EXPR)
+ {
+ splay_tree_node n
+ = splay_tree_lookup (id->decl_map,
+ (splay_tree_key) TREE_OPERAND (*tp, 0));
+ /* We _must_ have seen the enclosing LABELED_BLOCK_EXPR. */
+ if (! n)
+ abort ();
+ *tp = copy_node (*tp);
+ TREE_OPERAND (*tp, 0) = (tree) n->value;
+ }
+ #endif /* INLINER_FOR_JAVA */
/* Otherwise, just copy the node. Note that copy_tree_r already
knows not to copy VAR_DECLs, etc., so this is safe. */
*************** copy_body (id)
*** 457,464 ****
--- 577,591 ----
static tree
+ #ifndef INLINER_FOR_JAVA
initialize_inlined_parameters (id, args, fn)
+ #else /* INLINER_FOR_JAVA */
+ initialize_inlined_parameters (id, args, fn, block)
+ #endif /* INLINER_FOR_JAVA */
inline_data *id;
tree args;
tree fn;
+ #ifdef INLINER_FOR_JAVA
+ tree block;
+ #endif /* INLINER_FOR_JAVA */
{
tree init_stmts;
*************** initialize_inlined_parameters (id, args,
*** 466,469 ****
--- 593,599 ----
tree a;
tree p;
+ #ifdef INLINER_FOR_JAVA
+ tree vars = NULL_TREE;
+ #endif /* INLINER_FOR_JAVA */
/* Figure out what the parameters are. */
*************** initialize_inlined_parameters (id, args,
*** 478,482 ****
--- 608,614 ----
a = a ? TREE_CHAIN (a) : a, p = TREE_CHAIN (p))
{
+ #ifndef INLINER_FOR_JAVA
tree init_stmt;
+ #endif /* not INLINER_FOR_JAVA */
tree var;
tree value;
*************** initialize_inlined_parameters (id, args,
*** 527,533 ****
--- 659,670 ----
/* Declare this new variable. */
+ #ifndef INLINER_FOR_JAVA
init_stmt = build_stmt (DECL_STMT, var);
TREE_CHAIN (init_stmt) = init_stmts;
init_stmts = init_stmt;
+ #else /* INLINER_FOR_JAVA */
+ TREE_CHAIN (var) = vars;
+ vars = var;
+ #endif /* INLINER_FOR_JAVA */
/* Initialize this VAR_DECL from the equivalent argument. If
*************** initialize_inlined_parameters (id, args,
*** 537,540 ****
--- 674,678 ----
object will be constructed in VAR. */
if (! TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (p)))
+ #ifndef INLINER_FOR_JAVA
DECL_INITIAL (var) = value;
else
*************** initialize_inlined_parameters (id, args,
*** 574,579 ****
--- 712,732 ----
init_stmts = cleanup_stmt;
}
+ #else /* INLINER_FOR_JAVA */
+ {
+ tree assignment = build (MODIFY_EXPR, TREE_TYPE (p), var, value);
+ init_stmts = add_stmt_to_compound (init_stmts, TREE_TYPE (p),
+ assignment);
+ }
+ else
+ {
+ /* Java objects don't ever need constructing when being
+ passed as arguments because only call by reference is
+ supported. */
+ abort ();
+ }
+ #endif /* INLINER_FOR_JAVA */
}
+ #ifndef INLINER_FOR_JAVA
/* Evaluate trailing arguments. */
for (; a; a = TREE_CHAIN (a))
*************** initialize_inlined_parameters (id, args,
*** 593,596 ****
--- 746,753 ----
order. Straighten them out now. */
return nreverse (init_stmts);
+ #else /* INLINER_FOR_JAVA */
+ BLOCK_VARS (block) = nreverse (vars);
+ return init_stmts;
+ #endif /* INLINER_FOR_JAVA */
}
*************** initialize_inlined_parameters (id, args,
*** 601,611 ****
--- 758,778 ----
static tree
+ #ifndef INLINER_FOR_JAVA
declare_return_variable (id, use_stmt)
+ #else /* INLINER_FOR_JAVA */
+ declare_return_variable (id, var)
+ #endif /* INLINER_FOR_JAVA */
struct inline_data *id;
+ #ifndef INLINER_FOR_JAVA
tree *use_stmt;
+ #else /* INLINER_FOR_JAVA */
+ tree *var;
+ #endif /* INLINER_FOR_JAVA */
{
tree fn = VARRAY_TOP_TREE (id->fns);
tree result = DECL_RESULT (fn);
+ #ifndef INLINER_FOR_JAVA
tree var;
+ #endif /* not INLINER_FOR_JAVA */
int need_return_decl = 1;
*************** declare_return_variable (id, use_stmt)
*** 614,621 ****
--- 781,793 ----
if (!result || VOID_TYPE_P (TREE_TYPE (result)))
{
+ #ifndef INLINER_FOR_JAVA
*use_stmt = NULL_TREE;
+ #else /* INLINER_FOR_JAVA */
+ *var = NULL_TREE;
+ #endif /* INLINER_FOR_JAVA */
return NULL_TREE;
}
+ #ifndef INLINER_FOR_JAVA
var = ((*lang_hooks.tree_inlining.copy_res_decl_for_inlining)
(result, fn, VARRAY_TREE (id->fns, 0), id->decl_map,
*************** declare_return_variable (id, use_stmt)
*** 637,641 ****
build1 (NOP_EXPR, TREE_TYPE (TREE_TYPE (fn)),
var));
-
TREE_ADDRESSABLE (*use_stmt) = 1;
--- 809,812 ----
*************** declare_return_variable (id, use_stmt)
*** 644,647 ****
--- 815,830 ----
if (need_return_decl)
return build_stmt (DECL_STMT, var);
+ #else /* INLINER_FOR_JAVA */
+ *var = ((*lang_hooks.tree_inlining.copy_res_decl_for_inlining)
+ (result, fn, VARRAY_TREE (id->fns, 0), id->decl_map,
+ &need_return_decl, NULL_TREE));
+
+ splay_tree_insert (id->decl_map,
+ (splay_tree_key) result,
+ (splay_tree_value) *var);
+ DECL_IGNORED_P (*var) = 1;
+ if (need_return_decl)
+ return *var;
+ #endif /* INLINER_FOR_JAVA */
/* 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. */
*************** expand_call_inline (tp, walk_subtrees, d
*** 784,791 ****
tree expr;
tree stmt;
tree chain;
- tree fn;
tree scope_stmt;
tree use_stmt;
tree arg_inits;
tree *inlined_body;
--- 967,978 ----
tree expr;
tree stmt;
+ #ifndef INLINER_FOR_JAVA
tree chain;
tree scope_stmt;
tree use_stmt;
+ #else /* INLINER_FOR_JAVA */
+ tree retvar;
+ #endif /* INLINER_FOR_JAVA */
+ tree fn;
tree arg_inits;
tree *inlined_body;
*************** expand_call_inline (tp, walk_subtrees, d
*** 800,803 ****
--- 987,991 ----
if (TREE_CODE (*tp) == TARGET_EXPR)
{
+ #ifndef INLINER_FOR_JAVA
int i, len = first_rtl_op (TARGET_EXPR);
*************** expand_call_inline (tp, walk_subtrees, d
*** 825,828 ****
--- 1013,1019 ----
return NULL_TREE;
+ #else /* INLINER_FOR_JAVA */
+ abort ();
+ #endif /* INLINER_FOR_JAVA */
}
*************** expand_call_inline (tp, walk_subtrees, d
*** 870,873 ****
--- 1061,1065 ----
push_srcloc (DECL_SOURCE_FILE (fn), DECL_SOURCE_LINE (fn));
+ #ifndef INLINER_FOR_JAVA
/* Build a statement-expression containing code to initialize the
arguments, the actual inline expansion of the body, and a label
*************** expand_call_inline (tp, walk_subtrees, d
*** 879,882 ****
--- 1071,1083 ----
STMT_EXPR_NO_SCOPE (expr) = 1;
stmt = STMT_EXPR_STMT (expr);
+ #else /* INLINER_FOR_JAVA */
+ /* Build a block containing code to initialize the arguments, the
+ actual inline expansion of the body, and a label for the return
+ statements within the function to jump to. The type of the
+ statement expression is the return type of the function call. */
+ stmt = NULL;
+ expr = build (BLOCK, TREE_TYPE (TREE_TYPE (fn)), stmt);
+ #endif /* INLINER_FOR_JAVA */
+
/* Local declarations will be replaced by their equivalents in this
map. */
*************** expand_call_inline (tp, walk_subtrees, d
*** 886,889 ****
--- 1087,1091 ----
/* Initialize the parameters. */
+ #ifndef INLINER_FOR_JAVA
arg_inits = initialize_inlined_parameters (id, TREE_OPERAND (t, 1), fn);
/* Expand any inlined calls in the initializers. Do this before we
*************** expand_call_inline (tp, walk_subtrees, d
*** 894,897 ****
--- 1096,1115 ----
/* And add them to the tree. */
COMPOUND_BODY (stmt) = chainon (COMPOUND_BODY (stmt), arg_inits);
+ #else /* INLINER_FOR_JAVA */
+ arg_inits = initialize_inlined_parameters (id, TREE_OPERAND (t, 1), fn, expr);
+ if (arg_inits)
+ {
+ /* Expand any inlined calls in the initializers. Do this before we
+ push FN on the stack of functions we are inlining; we want to
+ inline calls to FN that appear in the initializers for the
+ parameters. */
+ expand_calls_inline (&arg_inits, id);
+
+ /* And add them to the tree. */
+ BLOCK_EXPR_BODY (expr) = add_stmt_to_compound (BLOCK_EXPR_BODY (expr),
+ TREE_TYPE (arg_inits),
+ arg_inits);
+ }
+ #endif /* INLINER_FOR_JAVA */
/* Record the function we are about to inline so that we can avoid
*************** expand_call_inline (tp, walk_subtrees, d
*** 921,924 ****
--- 1139,1143 ----
abort ();
+ #ifndef INLINER_FOR_JAVA
/* Create a block to put the parameters in. We have to do this
after the parameters have been remapped because remapping
*************** expand_call_inline (tp, walk_subtrees, d
*** 940,960 ****
--- 1159,1213 ----
= chainon (COMPOUND_BODY (stmt),
declare_return_variable (id, &use_stmt));
+ #else /* INLINER_FOR_JAVA */
+ {
+ /* Declare the return variable for the function. */
+ tree decl = declare_return_variable (id, &retvar);
+ if (retvar)
+ {
+ tree *next = &BLOCK_VARS (expr);
+ while (*next)
+ next = &TREE_CHAIN (*next);
+ *next = decl;
+ }
+ }
+ #endif /* INLINER_FOR_JAVA */
/* After we've initialized the parameters, we insert the body of the
function itself. */
+ #ifndef INLINER_FOR_JAVA
inlined_body = &COMPOUND_BODY (stmt);
while (*inlined_body)
inlined_body = &TREE_CHAIN (*inlined_body);
*inlined_body = copy_body (id);
+ #else /* INLINER_FOR_JAVA */
+ {
+ tree new_body = copy_body (id);
+ TREE_TYPE (new_body) = TREE_TYPE (TREE_TYPE (fn));
+ BLOCK_EXPR_BODY (expr)
+ = add_stmt_to_compound (BLOCK_EXPR_BODY (expr),
+ TREE_TYPE (new_body), new_body);
+ inlined_body = &BLOCK_EXPR_BODY (expr);
+ }
+ #endif /* INLINER_FOR_JAVA */
/* After the body of the function comes the RET_LABEL. This must come
before we evaluate the returned value below, because that evalulation
may cause RTL to be generated. */
+ #ifndef INLINER_FOR_JAVA
COMPOUND_BODY (stmt)
= chainon (COMPOUND_BODY (stmt),
build_stmt (LABEL_STMT, id->ret_label));
+ #else /* INLINER_FOR_JAVA */
+ {
+ tree label = build1 (LABEL_EXPR, void_type_node, id->ret_label);
+ BLOCK_EXPR_BODY (expr)
+ = add_stmt_to_compound (BLOCK_EXPR_BODY (expr), void_type_node, label);
+ TREE_SIDE_EFFECTS (label) = TREE_SIDE_EFFECTS (t);
+ }
+ #endif /* INLINER_FOR_JAVA */
/* Finally, mention the returned value so that the value of the
statement-expression is the returned value of the function. */
+ #ifndef INLINER_FOR_JAVA
COMPOUND_BODY (stmt) = chainon (COMPOUND_BODY (stmt), use_stmt);
*************** expand_call_inline (tp, walk_subtrees, d
*** 965,968 ****
--- 1218,1227 ----
COMPOUND_BODY (stmt)
= chainon (COMPOUND_BODY (stmt), scope_stmt);
+ #else /* INLINER_FOR_JAVA */
+ if (retvar)
+ BLOCK_EXPR_BODY (expr)
+ = add_stmt_to_compound (BLOCK_EXPR_BODY (expr),
+ TREE_TYPE (retvar), retvar);
+ #endif /* INLINER_FOR_JAVA */
/* Clean up. */
*************** expand_call_inline (tp, walk_subtrees, d
*** 976,984 ****
--- 1235,1251 ----
EXPR_WITH_FILE_LOCATION so that we'll get debugging line notes
pointing to the right place. */
+ #ifndef INLINER_FOR_JAVA
chain = TREE_CHAIN (*tp);
*tp = build_expr_wfl (expr, DECL_SOURCE_FILE (fn), DECL_SOURCE_LINE (fn),
/*col=*/0);
+ #else /* INLINER_FOR_JAVA */
+ *tp = build_expr_wfl (expr, DECL_SOURCE_FILE (fn),
+ DECL_SOURCE_LINE_FIRST(fn),
+ /*col=*/0);
+ #endif /* INLINER_FOR_JAVA */
EXPR_WFL_EMIT_LINE_NOTE (*tp) = 1;
+ #ifndef INLINER_FOR_JAVA
TREE_CHAIN (*tp) = chain;
+ #endif /* not INLINER_FOR_JAVA */
pop_srcloc ();
*************** expand_call_inline (tp, walk_subtrees, d
*** 1010,1014 ****
return NULL_TREE;
}
-
/* Walk over the entire tree *TP, replacing CALL_EXPRs with inline
expansions as appropriate. */
--- 1277,1280 ----
*************** walk_tree (tp, func, data, htab_)
*** 1175,1178 ****
--- 1441,1445 ----
code = TREE_CODE (*tp);
+ #ifndef INLINER_FOR_JAVA
/* Even if we didn't, FUNC may have decided that there was nothing
interesting below this point in the tree. */
*************** walk_tree (tp, func, data, htab_)
*** 1191,1201 ****
--- 1458,1477 ----
|| TREE_CODE_CLASS (code) == 'r'
|| TREE_CODE_CLASS (code) == 's')
+ #else /* INLINER_FOR_JAVA */
+ if (code != EXIT_BLOCK_EXPR
+ && code != SAVE_EXPR
+ && (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
+ || TREE_CODE_CLASS (code) == 'r'
+ || TREE_CODE_CLASS (code) == 's'))
+ #endif /* INLINER_FOR_JAVA */
{
int i, len;
+ #ifndef INLINER_FOR_JAVA
/* Set lineno here so we get the right instantiation context
if we call instantiate_decl from inlinable_function_p. */
if (statement_code_p (code) && !STMT_LINENO_FOR_FN_P (*tp))
lineno = STMT_LINENO (*tp);
+ #endif /* not INLINER_FOR_JAVA */
/* Walk over all the sub-trees of this operand. */
*************** walk_tree (tp, func, data, htab_)
*** 1211,1214 ****
--- 1487,1491 ----
WALK_SUBTREE (TREE_OPERAND (*tp, i));
+ #ifndef INLINER_FOR_JAVA
/* For statements, we also walk the chain so that we cover the
entire statement tree. */
*************** walk_tree (tp, func, data, htab_)
*** 1233,1236 ****
--- 1510,1514 ----
}
+ #endif /* not INLINER_FOR_JAVA */
/* We didn't find what we were looking for. */
return NULL_TREE;
*************** walk_tree (tp, func, data, htab_)
*** 1328,1331 ****
--- 1606,1617 ----
WALK_SUBTREE_TAIL (TYPE_OFFSET_BASETYPE (*tp));
+ #ifdef INLINER_FOR_JAVA
+ case EXIT_BLOCK_EXPR:
+ WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 1));
+
+ case SAVE_EXPR:
+ WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 0));
+ #endif /* INLINER_FOR_JAVA */
+
default:
abort ();
*************** copy_tree_r (tp, walk_subtrees, data)
*** 1385,1388 ****
--- 1671,1675 ----
walk_tree to walk into the chain as well. */
if (code == PARM_DECL || code == TREE_LIST
+ #ifndef INLINER_FOR_JAVA
|| (*lang_hooks.tree_inlining.tree_chain_matters_p) (*tp)
|| statement_code_p (code))
*************** copy_tree_r (tp, walk_subtrees, data)
*** 1393,1396 ****
--- 1680,1687 ----
if (TREE_CODE (*tp) == SCOPE_STMT)
SCOPE_STMT_BLOCK (*tp) = NULL_TREE;
+ #else /* INLINER_FOR_JAVA */
+ || (*lang_hooks.tree_inlining.tree_chain_matters_p) (*tp))
+ TREE_CHAIN (*tp) = chain;
+ #endif /* INLINER_FOR_JAVA */
}
else if (TREE_CODE_CLASS (code) == 't')
*************** remap_save_expr (tp, st_, fn, walk_subtr
*** 1445,1446 ****
--- 1736,1755 ----
*tp = (tree) n->value;
}
+
+ #ifdef INLINER_FOR_JAVA
+ /* Add STMT to EXISTING if possible, otherwise create a new
+ COMPOUND_EXPR and add STMT to it. */
+
+ static tree
+ add_stmt_to_compound (existing, type, stmt)
+ tree existing, type, stmt;
+ {
+ if (!stmt)
+ return existing;
+ else if (existing)
+ return build (COMPOUND_EXPR, type, existing, stmt);
+ else
+ return stmt;
+ }
+
+ #endif /* INLINER_FOR_JAVA */
Index: java/Make-lang.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/Make-lang.in,v
retrieving revision 1.88
diff -p -2 -c -r1.88 Make-lang.in
*** java/Make-lang.in 11 Jun 2002 14:58:09 -0000 1.88
--- java/Make-lang.in 30 Jul 2002 12:46:12 -0000
*************** JAVA_OBJS = java/parse.o java/class.o ja
*** 110,114 ****
java/mangle_name.o java/builtins.o \
java/jcf-write.o java/buffer.o java/check-init.o java/jcf-depend.o \
! java/jcf-path.o java/xref.o java/boehm.o mkdeps.o
GCJH_OBJS = java/gjavah.o java/jcf-io.o java/jcf-depend.o java/jcf-path.o \
--- 110,114 ----
java/mangle_name.o java/builtins.o \
java/jcf-write.o java/buffer.o java/check-init.o java/jcf-depend.o \
! java/jcf-path.o java/xref.o java/boehm.o java/java-tree-inline.o mkdeps.o
GCJH_OBJS = java/gjavah.o java/jcf-io.o java/jcf-depend.o java/jcf-path.o \
*************** java/expr.o: java/expr.c $(CONFIG_H) $(J
*** 289,292 ****
--- 289,299 ----
java/java-except.h java/java-except.h java/parse.h toplev.h \
$(SYSTEM_H) $(GGC_H) gt-java-expr.h
+ java/java-tree-inline.o: tree-inline.c $(CONFIG_H) $(SYSTEM_H) \
+ $(TREE_H) $(RTL_H) expr.h flags.h params.h input.h insn-config.h \
+ $(INTEGRATE_H) $(VARRAY_H) $(HASHTAB_H) $(SPLAY_TREE_H) toplev.h \
+ langhooks.h $(C_COMMON_H) $(srcdir)/tree-inline.h
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ -DINLINER_FOR_JAVA=1 \
+ $(srcdir)/tree-inline.c -o $@
java/jcf-depend.o: java/jcf-depend.c $(CONFIG_H) $(SYSTEM_H) java/jcf.h
java/jcf-parse.o: java/jcf-parse.c $(CONFIG_H) $(JAVA_TREE_H) flags.h \
Index: java/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/decl.c,v
retrieving revision 1.130
diff -p -2 -c -r1.130 decl.c
*** java/decl.c 1 Jul 2002 23:07:18 -0000 1.130
--- java/decl.c 30 Jul 2002 12:46:13 -0000
*************** The Free Software Foundation is independ
*** 42,48 ****
#include "java-except.h"
#include "ggc.h"
#if defined (DEBUG_JAVA_BINDING_LEVELS)
! extern void indent PROTO((void));
#endif
--- 42,50 ----
#include "java-except.h"
#include "ggc.h"
+ #include "timevar.h"
+ #include "tree-inline.h"
#if defined (DEBUG_JAVA_BINDING_LEVELS)
! extern void indent PARAMS ((void));
#endif
*************** static tree create_primitive_vtable PARA
*** 54,57 ****
--- 56,60 ----
static tree check_local_named_variable PARAMS ((tree, tree, int, int *));
static tree check_local_unnamed_variable PARAMS ((tree, tree, tree));
+ static void dump_function PARAMS ((enum tree_dump_index, tree));
/* Set to non-zero value in order to emit class initilization code
*************** build_result_decl (fndecl)
*** 1663,1671 ****
{
tree restype = TREE_TYPE (TREE_TYPE (fndecl));
! /* To be compatible with C_PROMOTING_INTEGER_TYPE_P in cc1/cc1plus. */
! if (INTEGRAL_TYPE_P (restype)
! && TYPE_PRECISION (restype) < TYPE_PRECISION (integer_type_node))
! restype = integer_type_node;
! return (DECL_RESULT (fndecl) = build_decl (RESULT_DECL, NULL_TREE, restype));
}
--- 1666,1681 ----
{
tree restype = TREE_TYPE (TREE_TYPE (fndecl));
! tree result = DECL_RESULT (fndecl);
! if (! result)
! {
! /* To be compatible with C_PROMOTING_INTEGER_TYPE_P in cc1/cc1plus. */
! if (INTEGRAL_TYPE_P (restype)
! && TYPE_PRECISION (restype) < TYPE_PRECISION (integer_type_node))
! restype = integer_type_node;
! result = build_decl (RESULT_DECL, NULL_TREE, restype);
! DECL_CONTEXT (result) = fndecl;
! DECL_RESULT (fndecl) = result;
! }
! return result;
}
*************** end_java_method ()
*** 1824,1827 ****
--- 1834,1888 ----
current_function_decl = NULL_TREE;
+ }
+
+ /* Dump FUNCTION_DECL FN as tree dump PHASE. */
+
+ static void
+ dump_function (phase, fn)
+ enum tree_dump_index phase;
+ tree fn;
+ {
+ FILE *stream;
+ int flags;
+
+ stream = dump_begin (phase, &flags);
+ if (stream)
+ {
+ dump_node (fn, TDF_SLIM | flags, stream);
+ dump_end (phase, stream);
+ }
+ }
+
+ void java_optimize_inline (fndecl)
+ tree fndecl;
+ {
+ if (flag_inline_trees)
+ {
+ int uninlinable;
+ /* First, cache whether the current function is inlinable. Some
+ predicates depend on cfun and current_function_decl to
+ function completely. */
+ timevar_push (TV_INTEGRATION);
+ uninlinable = ! tree_inlinable_function_p (fndecl);
+
+ #if 0
+ if (! uninlinable
+ /* Save function tree for inlining. Should return 0 if the
+ language does not support function deferring or the
+ function could not be deferred. */
+ && defer_fn (fndecl))
+ {
+ /* Let the back-end know that this function exists. */
+ (*debug_hooks->deferred_inline_function) (fndecl);
+ timevar_pop (TV_INTEGRATION);
+ return;
+ }
+ #endif
+
+ /* Then, inline any functions called in it. */
+ optimize_inline_calls (fndecl);
+ timevar_pop (TV_INTEGRATION);
+ dump_function (TDI_inlined, fndecl);
+ }
}
Index: java/expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/expr.c,v
retrieving revision 1.148
diff -p -2 -c -r1.148 expr.c
*** java/expr.c 25 Jun 2002 13:27:19 -0000 1.148
--- java/expr.c 30 Jul 2002 12:46:15 -0000
*************** java_expand_expr (exp, target, tmode, mo
*** 2536,2539 ****
--- 2536,2540 ----
{
tree local;
+ rtx last;
tree body = BLOCK_EXPR_BODY (exp);
/* Set to 1 or more when we found a static class
*************** java_expand_expr (exp, target, tmode, mo
*** 2569,2577 ****
body = TREE_OPERAND (body, 1);
}
! expand_expr (body, const0_rtx, VOIDmode, 0);
emit_queue ();
expand_end_bindings (getdecls (), 1, 0);
poplevel (1, 1, 0);
! return const0_rtx;
}
return const0_rtx;
--- 2570,2578 ----
body = TREE_OPERAND (body, 1);
}
! last = expand_expr (body, NULL_RTX, VOIDmode, 0);
emit_queue ();
expand_end_bindings (getdecls (), 1, 0);
poplevel (1, 1, 0);
! return last;
}
return const0_rtx;
*************** java_expand_expr (exp, target, tmode, mo
*** 2629,2632 ****
--- 2630,2638 ----
return expand_expr (build_exception_object_ref (TREE_TYPE (exp)),
target, tmode, modifier);
+
+ case LABEL_EXPR:
+ /* Used only by expanded inline functions. */
+ expand_label (TREE_OPERAND (exp, 0));
+ return const0_rtx;
default:
Index: java/java-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/java-tree.h,v
retrieving revision 1.153
diff -p -2 -c -r1.153 java-tree.h
*** java/java-tree.h 11 Jun 2002 17:31:10 -0000 1.153
--- java/java-tree.h 30 Jul 2002 12:46:16 -0000
*************** union lang_tree_node
*** 903,906 ****
--- 903,912 ----
#define DECL_FIELD_FINAL_WFL(NODE) \
(DECL_LANG_SPECIFIC(NODE)->u.v.wfl)
+ /* In a FUNCTION_DECL for which DECL_BUILT_IN does not hold, this is
+ the approximate number of statements in this function. There is
+ no need for this number to be exact; it is only used in various
+ heuristics regarding optimization. */
+ #define DECL_NUM_STMTS(NODE) \
+ (FUNCTION_DECL_CHECK (NODE)->decl.u1.i)
/* True if NODE is a local variable final. */
#define LOCAL_FINAL_P(NODE) (DECL_LANG_SPECIFIC (NODE) && DECL_FINAL (NODE))
*************** extern void append_gpp_mangled_name PARA
*** 1274,1277 ****
--- 1280,1286 ----
extern void add_predefined_file PARAMS ((tree));
extern int predefined_filename_p PARAMS ((tree));
+
+ extern void java_optimize_inline PARAMS ((tree));
+ extern tree decl_constant_value PARAMS ((tree));
#if defined(RTX_CODE) && defined (HAVE_MACHINE_MODES)
Index: java/lang.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/lang.c,v
retrieving revision 1.105
diff -p -2 -c -r1.105 lang.c
*** java/lang.c 22 Jul 2002 00:42:54 -0000 1.105
--- java/lang.c 30 Jul 2002 12:46:16 -0000
*************** The Free Software Foundation is independ
*** 41,44 ****
--- 41,45 ----
#include "ggc.h"
#include "diagnostic.h"
+ #include "tree-inline.h"
struct string_option
*************** static int process_option_with_no PARAMS
*** 62,65 ****
--- 63,71 ----
const struct string_option *,
int));
+ static tree java_tree_inlining_walk_subtrees PARAMS ((tree *,
+ int *,
+ walk_tree_fn,
+ void *,
+ void *));
static int java_unsafe_for_reeval PARAMS ((tree));
*************** struct language_function GTY(())
*** 266,269 ****
--- 272,278 ----
#define LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE java_signed_or_unsigned_type
+ #undef LANG_HOOKS_TREE_INLINING_WALK_SUBTREES
+ #define LANG_HOOKS_TREE_INLINING_WALK_SUBTREES java_tree_inlining_walk_subtrees
+
/* Each front end provides its own. */
const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
*************** java_init (filename)
*** 497,500 ****
--- 506,512 ----
#endif
+ if (flag_inline_functions)
+ flag_inline_trees = 1;
+
/* Open input file. */
*************** static bool
*** 787,795 ****
java_post_options ()
{
! /* Turn off RTL inliner unless -finline-functions was really specified. */
! if (flag_really_inline == 0)
{
! flag_no_inline = 1;
! flag_inline_functions = 0;
}
--- 799,884 ----
java_post_options ()
{
! /* Use tree inlining if possible. Function instrumentation is only
! done in the RTL level, so we disable tree inlining. */
! if (! flag_instrument_function_entry_exit)
! {
! if (!flag_no_inline)
! flag_no_inline = 1;
! if (flag_inline_functions)
! {
! flag_inline_trees = 2;
! flag_inline_functions = 0;
! }
! }
!
! }
!
! /* Return either DECL or its known constant value (if it has one). */
!
! tree
! decl_constant_value (decl)
! tree decl;
! {
! if (/* Don't change a variable array bound or initial value to a constant
! in a place where a variable is invalid. */
! current_function_decl != 0
! && ! TREE_THIS_VOLATILE (decl)
! && TREE_READONLY (decl)
! && DECL_INITIAL (decl) != 0
! && TREE_CODE (DECL_INITIAL (decl)) != ERROR_MARK
! /* This is invalid if initial value is not constant.
! If it has either a function call, a memory reference,
! or a variable, then re-evaluating it could give different results. */
! && TREE_CONSTANT (DECL_INITIAL (decl))
! /* Check for cases where this is sub-optimal, even though valid. */
! && TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR)
! return DECL_INITIAL (decl);
! return decl;
! }
!
! /* Walk the language specific tree nodes during inlining. */
!
! static tree
! java_tree_inlining_walk_subtrees (tp,subtrees,func,data,htab)
! tree *tp ATTRIBUTE_UNUSED;
! int *subtrees ATTRIBUTE_UNUSED;
! walk_tree_fn func ATTRIBUTE_UNUSED;
! void *data ATTRIBUTE_UNUSED;
! void *htab ATTRIBUTE_UNUSED;
! {
! enum tree_code code;
! tree result;
!
! #define WALK_SUBTREE(NODE) \
! do \
! { \
! result = walk_tree (&(NODE), func, data, htab); \
! if (result) \
! return result; \
! } \
! while (0)
!
! tree t = *tp;
! if (!t)
! return NULL_TREE;
!
! code = TREE_CODE (t);
! switch (code)
{
! case BLOCK:
! if (BLOCK_EXPR_BODY (t))
! {
! tree *prev = &BLOCK_EXPR_BODY (*tp);
! while (*prev)
! {
! WALK_SUBTREE (*prev);
! prev = &TREE_CHAIN (*prev);
! }
! }
! return NULL_TREE;
! break;
!
! default:
! return NULL_TREE;
}
Index: java/parse.y
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/parse.y,v
retrieving revision 1.390
diff -p -2 -c -r1.390 parse.y
*** java/parse.y 2 Jul 2002 02:56:11 -0000 1.390
--- java/parse.y 30 Jul 2002 12:46:24 -0000
*************** definitions and other extensions. */
*** 68,71 ****
--- 68,72 ----
#include "ggc.h"
#include "debug.h"
+ #include "tree-inline.h"
#ifndef DIR_SEPARATOR
*************** source_end_java_method ()
*** 7479,7482 ****
--- 7480,7485 ----
dump_java_tree (TDI_original, fndecl);
+ java_optimize_inline (fndecl);
+
/* Generate function's code */
if (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (fndecl))
*************** add_stmt_to_compound (existing, type, st
*** 7540,7543 ****
--- 7543,7550 ----
tree existing, type, stmt;
{
+ /* Keep track of this for inlining. */
+ if (current_function_decl)
+ ++DECL_NUM_STMTS (current_function_decl);
+
if (existing)
return build (COMPOUND_EXPR, type, existing, stmt);
*************** java_expand_method_bodies (class)
*** 8129,8132 ****
--- 8136,8144 ----
current_function_decl = decl;
+ /* Save the function for inlining. */
+ if (flag_inline_trees)
+ DECL_SAVED_TREE (decl) =
+ BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (decl));
+
/* It's time to assign the variable flagging static class
initialization based on which classes invoked static methods