From 7149627b8ede8a1f9b4735da0690f8b28209503e Mon Sep 17 00:00:00 2001 From: Andrew Haley Date: Fri, 16 Aug 2002 10:32:30 +0000 Subject: [PATCH] Make-lang.in (java-tree-inline.o): New. 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. From-SVN: r56377 --- gcc/java/ChangeLog | 23 +++++++++++ gcc/java/Make-lang.in | 9 +++- gcc/java/decl.c | 52 ++++++++++++++++++++--- gcc/java/expr.c | 10 ++++- gcc/java/java-tree.h | 9 ++++ gcc/java/lang.c | 96 +++++++++++++++++++++++++++++++++++++++++-- gcc/java/parse.y | 12 ++++++ 7 files changed, 198 insertions(+), 13 deletions(-) diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index da858f272b9..9f35084a236 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,26 @@ +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. + 2002-08-13 Jesse Rosenstock For PR java/7483: diff --git a/gcc/java/Make-lang.in b/gcc/java/Make-lang.in index 5b5f2a9e0a8..50f811bb470 100644 --- a/gcc/java/Make-lang.in +++ b/gcc/java/Make-lang.in @@ -109,7 +109,7 @@ JAVA_OBJS = java/parse.o java/class.o java/decl.o java/expr.o \ java/zextract.o java/jcf-io.o java/jcf-parse.o java/mangle.o \ 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 + 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/zextract.o version.o mkdeps.o errors.o @@ -289,6 +289,13 @@ java/expr.o: java/expr.c $(CONFIG_H) $(JAVA_TREE_H) java/jcf.h real.h \ $(RTL_H) $(EXPR_H) java/javaop.h java/java-opcodes.h except.h \ 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 \ input.h java/java-except.h $(SYSTEM_H) toplev.h java/parse.h $(GGC_H) \ diff --git a/gcc/java/decl.c b/gcc/java/decl.c index bf5e5ff5192..9f055d3cf57 100644 --- a/gcc/java/decl.c +++ b/gcc/java/decl.c @@ -41,9 +41,11 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */ #include "except.h" #include "java-except.h" #include "ggc.h" +#include "timevar.h" +#include "tree-inline.h" #if defined (DEBUG_JAVA_BINDING_LEVELS) -extern void indent PROTO((void)); +extern void indent PARAMS ((void)); #endif static tree push_jvm_slot PARAMS ((int, tree)); @@ -53,6 +55,7 @@ static struct binding_level *make_binding_level PARAMS ((void)); static tree create_primitive_vtable PARAMS ((const char *)); 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 before static field references. */ @@ -1662,11 +1665,18 @@ build_result_decl (fndecl) tree fndecl; { 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)); + 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; } void @@ -1825,4 +1835,34 @@ end_java_method () 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) + { + timevar_push (TV_INTEGRATION); + optimize_inline_calls (fndecl); + timevar_pop (TV_INTEGRATION); + dump_function (TDI_inlined, fndecl); + } +} + #include "gt-java-decl.h" diff --git a/gcc/java/expr.c b/gcc/java/expr.c index 133fa039b45..d6a443dca9a 100644 --- a/gcc/java/expr.c +++ b/gcc/java/expr.c @@ -2534,6 +2534,7 @@ java_expand_expr (exp, target, tmode, modifier) if (BLOCK_EXPR_BODY (exp)) { tree local; + rtx last; tree body = BLOCK_EXPR_BODY (exp); /* Set to 1 or more when we found a static class initialization flag. */ @@ -2567,11 +2568,11 @@ java_expand_expr (exp, target, tmode, modifier) emit_queue (); body = TREE_OPERAND (body, 1); } - expand_expr (body, const0_rtx, VOIDmode, 0); + last = expand_expr (body, NULL_RTX, VOIDmode, 0); emit_queue (); expand_end_bindings (getdecls (), 1, 0); poplevel (1, 1, 0); - return const0_rtx; + return last; } return const0_rtx; @@ -2628,6 +2629,11 @@ java_expand_expr (exp, target, tmode, modifier) 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: internal_error ("can't expand %s", tree_code_name [TREE_CODE (exp)]); } diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h index 8a7fb9e9366..a08ec5830fc 100644 --- a/gcc/java/java-tree.h +++ b/gcc/java/java-tree.h @@ -902,6 +902,12 @@ union lang_tree_node /* The original WFL of a final variable. */ #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)) /* True if NODE is a final field. */ @@ -1274,6 +1280,9 @@ extern void append_gpp_mangled_name PARAMS ((const char *, int)); 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) struct rtx_def * java_expand_expr PARAMS ((tree, rtx, enum machine_mode, int)); diff --git a/gcc/java/lang.c b/gcc/java/lang.c index 6d7affacbc9..0a76402f555 100644 --- a/gcc/java/lang.c +++ b/gcc/java/lang.c @@ -40,6 +40,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */ #include "xref.h" #include "ggc.h" #include "diagnostic.h" +#include "tree-inline.h" struct string_option { @@ -61,6 +62,11 @@ static void java_print_error_function PARAMS ((diagnostic_context *, static int process_option_with_no PARAMS ((const char *, 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)); #ifndef TARGET_OBJECT_SUFFIX @@ -265,6 +271,9 @@ struct language_function GTY(()) #undef LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE #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; @@ -496,6 +505,9 @@ java_init (filename) flag_minimal_debug = 0; #endif + if (flag_inline_functions) + flag_inline_trees = 1; + /* Open input file. */ if (filename == 0 || !strcmp (filename, "-")) @@ -786,17 +798,93 @@ java_init_options () static bool java_post_options () { - /* Turn off RTL inliner unless -finline-functions was really specified. */ - if (flag_really_inline == 0) + /* 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) { - flag_no_inline = 1; - flag_inline_functions = 0; + if (!flag_no_inline) + flag_no_inline = 1; + if (flag_inline_functions) + { + flag_inline_trees = 2; + flag_inline_functions = 0; + } } /* Initialize the compiler back end. */ return false; } +/* 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; + } +} + /* Called from unsafe_for_reeval. */ static int java_unsafe_for_reeval (t) diff --git a/gcc/java/parse.y b/gcc/java/parse.y index 2a581a156c7..3dabe3593d0 100644 --- a/gcc/java/parse.y +++ b/gcc/java/parse.y @@ -67,6 +67,7 @@ definitions and other extensions. */ #include "except.h" #include "ggc.h" #include "debug.h" +#include "tree-inline.h" #ifndef DIR_SEPARATOR #define DIR_SEPARATOR '/' @@ -7478,6 +7479,8 @@ source_end_java_method () patched. Dump it to a file if the user requested it. */ dump_java_tree (TDI_original, fndecl); + java_optimize_inline (fndecl); + /* Generate function's code */ if (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (fndecl)) && ! flag_emit_class_files @@ -7539,6 +7542,10 @@ static tree add_stmt_to_compound (existing, type, stmt) 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); else @@ -8128,6 +8135,11 @@ java_expand_method_bodies (class) 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 are definitely initializing. This should be flagged. */