2002-07-30 Andrew Haley * 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 * 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