This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] unit-at-a-time for java


I thought I'd give this a try, since it enables effective cross-module
inlining for gcj.  Following is the patch I'm testing.  There are two
parts: a patchlet to cgraphunit.c, and the java frontend changes and
bugfixes I needed to make -funit-at-a-time work.

Jan, I'm not sure what the comment regarding current_function_decl means.
However the java inliner requires this to be set to the outermost calling
function.  I don't know what the impact to C/C++ is.  (If that won't work
I suppose we could introduce a new variable.)

Calling walk_tree_with_duplicates turned out to be necessary to avoid
infinite recursion when gathering costs.

For gcj, I broke out the rtl expansion calls from parse.y into a new
function java_expand_body, which is also the expand_body langhook for
cgraphunit.  Class initialization and synchronized methods are handled by
patching the tree instead of emitting RTL directly, as the latter cannot
be inlined as trees.

Compiling a small Java application with 185 classes and 946 methods as a
single unit, I get:

-O3:

Execution times (seconds)
 TOTAL                 :  71.84             0.71            73.73

   text    data     bss     dec     hex filename
 433128   87108     392  520628   7f1b4 lib/jacl_all.o

-O2:

Execution times (seconds)
 TOTAL                 :  56.92             0.41            57.80

   text    data     bss     dec     hex filename
 412280   86980     392  499652   79fc4 lib/jacl_all.o

-O1:

Execution times (seconds)
 TOTAL                 :  31.65             0.50            32.40

   text    data     bss     dec     hex filename
 406480   86980     392  493852   7891c lib/jacl_all.o

I also have a similar, much simpler patch for tree-ssa.

Bootstrapped on i686-pc-linux-gnu.  Full regression test pending.

Jeff


2003-07-21  Jeff Sturm  <jsturm@one-point.com>

	* cgraphunit.c (record_call_1): Use walk_tree_without_duplicates.
	(cgraph_optimize_function): Set current_function_decl to the
	fndecl we're integrating from.

Index: cgraphunit.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cgraphunit.c,v
retrieving revision 1.16
diff -c -p -r1.16 cgraphunit.c
*** cgraphunit.c	13 Jul 2003 08:40:07 -0000	1.16
--- cgraphunit.c	22 Jul 2003 01:16:35 -0000
*************** record_call_1 (tree *tp, int *walk_subtr
*** 118,124 ****
  	     taken by something that is not a function call.  So only
  	     walk the function parameter list, skip the other subtrees.  */

! 	  walk_tree (&TREE_OPERAND (*tp, 1), record_call_1, data, NULL);
  	  *walk_subtrees = 0;
  	}
      }
--- 118,125 ----
  	     taken by something that is not a function call.  So only
  	     walk the function parameter list, skip the other subtrees.  */

! 	  walk_tree_without_duplicates (&TREE_OPERAND (*tp, 1),
! 					record_call_1, data);
  	  *walk_subtrees = 0;
  	}
      }
*************** cgraph_optimize_function (struct cgraph_
*** 276,282 ****

    timevar_push (TV_INTEGRATION);
    /* optimize_inline_calls avoids inlining of current_function_decl.  */
!   current_function_decl = 0;
    if (flag_inline_trees)
      optimize_inline_calls (decl);
    if (node->nested)
--- 277,283 ----

    timevar_push (TV_INTEGRATION);
    /* optimize_inline_calls avoids inlining of current_function_decl.  */
!   current_function_decl = decl;
    if (flag_inline_trees)
      optimize_inline_calls (decl);
    if (node->nested)



2003-07-21  Jeff Sturm  <jsturm@one-point.com>

	* expr.c: Include timevar.h, function.h and tree-inline.h.
	(java_expand_body): New function.
	* java-tree.h (java_expand_body): Declare.
	* jcf-parse.c (cgraph.h): Include.
	(java_parse_file): Handle flag_unit_at_a_time.
	* lang.c (LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION): Define.
	* parse.h (start_complete_expand_method): Declare.
	* parse.y: Include cgraph.h.
	(block): Don't special-case empty block production.
	(craft_constructor): Set DECL_INLINE.
	(source_end_java_method): Handle flag_unit_at_a_time.
	Call java_expand_body.
	(start_complete_expand_method): Remove `static' modifier.
	Patch function tree for	class initialization and/or
	synchronization as needed.  Don't begin RTL expansion yet.
	(java_complete_lhs): Ensure COMPOUND_EXPR has non-NULL type.
	(patch_assignment): Set DECL_CONTEXT on temporary variable.

Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/expr.c,v
retrieving revision 1.168
diff -c -p -r1.168 expr.c
*** expr.c	15 Jul 2003 05:32:21 -0000	1.168
--- expr.c	22 Jul 2003 01:16:59 -0000
*************** The Free Software Foundation is independ
*** 43,48 ****
--- 43,51 ----
  #include "toplev.h"
  #include "except.h"
  #include "ggc.h"
+ #include "timevar.h"
+ #include "function.h"
+ #include "tree-inline.h"

  static void flush_quick_stack (void);
  static void push_value (tree);
*************** java_expand_expr (tree exp, rtx target,
*** 2590,2595 ****
--- 2593,2649 ----
      default:
        internal_error ("can't expand %s", tree_code_name [TREE_CODE (exp)]);
      }
+ }
+
+ void
+ java_expand_body (tree fndecl)
+ {
+   const char *saved_input_filename = input_filename;
+   int saved_lineno = input_line;
+
+   current_function_decl = fndecl;
+   input_filename = DECL_SOURCE_FILE (fndecl);
+   input_line = DECL_SOURCE_LINE (fndecl);
+
+   timevar_push (TV_EXPAND);
+
+   /* Prepare the function for tree completion.  */
+   start_complete_expand_method (fndecl);
+
+   if (! flag_emit_class_files && ! flag_emit_xref)
+     {
+       /* Initialize the RTL code for the function.  */
+       init_function_start (fndecl);
+
+       /* Set up parameters and prepare for return, for the function.  */
+       expand_function_start (fndecl, 0);
+
+       /* Generate the RTL for this function.  */
+       expand_expr_stmt_value (DECL_SAVED_TREE (fndecl), 0, 1);
+     }
+
+   /* Pop out of its parameters.  */
+   pushdecl_force_head (DECL_ARGUMENTS (fndecl));
+   poplevel (1, 0, 1);
+   BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
+
+   if (! flag_emit_class_files && ! flag_emit_xref)
+     {
+       /* Generate rtl for function exit.  */
+       input_line = DECL_FUNCTION_LAST_LINE (fndecl);
+       expand_function_end ();
+
+       /* Run the optimizers and output the assembler code
+ 	 for this function.  */
+       rest_of_compilation (fndecl);
+     }
+
+   input_filename = saved_input_filename;
+   input_line = saved_lineno;
+
+   current_function_decl = NULL_TREE;
+
+   timevar_pop (TV_EXPAND);
  }

  /* Go over METHOD's bytecode and note instruction starts in
Index: java-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/java-tree.h,v
retrieving revision 1.177
diff -c -p -r1.177 java-tree.h
*** java-tree.h	9 Jul 2003 00:31:20 -0000	1.177
--- java-tree.h	22 Jul 2003 01:17:01 -0000
*************** enum
*** 1764,1767 ****
--- 1764,1770 ----
  };

  #undef DEBUG_JAVA_BINDING_LEVELS
+
+ extern void java_expand_body (tree);
+
  #endif /* ! GCC_JAVA_TREE_H */
Index: jcf-parse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/jcf-parse.c,v
retrieving revision 1.142
diff -c -p -r1.142 jcf-parse.c
*** jcf-parse.c	28 Jun 2003 00:30:31 -0000	1.142
--- jcf-parse.c	22 Jul 2003 01:17:01 -0000
*************** The Free Software Foundation is independ
*** 42,47 ****
--- 42,48 ----
  #include "debug.h"
  #include "assert.h"
  #include "tm_p.h"
+ #include "cgraph.h"

  #ifdef HAVE_LOCALE_H
  #include <locale.h>
*************** java_parse_file (int set_yydebug ATTRIBU
*** 1119,1124 ****
--- 1120,1131 ----
    java_expand_classes ();
    if (!java_report_errors () && !flag_syntax_only)
      {
+       if (flag_unit_at_a_time)
+ 	{
+ 	  cgraph_finalize_compilation_unit ();
+ 	  cgraph_optimize ();
+ 	}
+
        emit_register_classes ();
        if (flag_indirect_dispatch)
  	emit_offset_symbol_table ();
Index: lang.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/lang.c,v
retrieving revision 1.141
diff -c -p -r1.141 lang.c
*** lang.c	17 Jul 2003 13:25:21 -0000	1.141
--- lang.c	22 Jul 2003 01:17:01 -0000
*************** struct language_function GTY(())
*** 259,264 ****
--- 259,267 ----
  #undef LANG_HOOKS_DECL_OK_FOR_SIBCALL
  #define LANG_HOOKS_DECL_OK_FOR_SIBCALL java_decl_ok_for_sibcall

+ #undef LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION
+ #define LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION java_expand_body
+
  /* Each front end provides its own.  */
  const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;

Index: parse.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/parse.h,v
retrieving revision 1.91
diff -c -p -r1.91 parse.h
*** parse.h	9 Jun 2003 12:57:15 -0000	1.91
--- parse.h	22 Jul 2003 01:17:02 -0000
*************** ATTRIBUTE_NORETURN
*** 941,946 ****
--- 941,947 ----
  #endif
  ;
  extern void java_expand_classes (void);
+ extern void start_complete_expand_method (tree);

  extern GTY(()) struct parser_ctxt *ctxp;
  extern GTY(()) struct parser_ctxt *ctxp_for_generation;
Index: parse.y
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/parse.y,v
retrieving revision 1.437
diff -c -p -r1.437 parse.y
*** parse.y	9 Jul 2003 00:31:20 -0000	1.437
--- parse.y	22 Jul 2003 01:17:11 -0000
*************** definitions and other extensions.  */
*** 71,76 ****
--- 71,77 ----
  #include "ggc.h"
  #include "debug.h"
  #include "tree-inline.h"
+ #include "cgraph.h"

  /* Local function prototypes */
  static char *java_accstring_lookup (int);
*************** static tree java_complete_tree (tree);
*** 141,147 ****
  static tree maybe_generate_pre_expand_clinit (tree);
  static int analyze_clinit_body (tree, tree);
  static int maybe_yank_clinit (tree);
- static void start_complete_expand_method (tree);
  static void java_complete_expand_method (tree);
  static void java_expand_method_bodies (tree);
  static int  unresolved_type_p (tree, tree *);
--- 142,147 ----
*************** variable_initializers:
*** 1349,1362 ****

  /* 19.11 Production from 14: Blocks and Statements  */
  block:
! 	OCB_TK CCB_TK
! 		{
! 		  /* Store the location of the `}' when doing xrefs */
! 		  if (current_function_decl && flag_emit_xref)
! 		    DECL_END_SOURCE_LINE (current_function_decl) =
! 		      EXPR_WFL_ADD_COL ($2.location, 1);
! 		  $$ = empty_stmt_node;
! 		}
  |	block_begin block_statements block_end
  		{ $$ = $3; }
  ;
--- 1349,1356 ----

  /* 19.11 Production from 14: Blocks and Statements  */
  block:
! 	block_begin block_end
! 		{ $$ = $2; }
  |	block_begin block_statements block_end
  		{ $$ = $3; }
  ;
*************** craft_constructor (tree class_decl, tree
*** 5402,5407 ****
--- 5396,5402 ----
    /* Now, mark the artificial parameters. */
    DECL_FUNCTION_NAP (decl) = artificial;
    DECL_FUNCTION_SYNTHETIC_CTOR (decl) = DECL_CONSTRUCTOR_P (decl) = 1;
+   DECL_INLINE (decl) = 1;
    return decl;
  }

*************** source_end_java_method (void)
*** 7369,7398 ****
       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
!       && ! flag_emit_xref)
!     expand_expr_stmt (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (fndecl)));
!
!   /* pop out of its parameters */
!   pushdecl_force_head (DECL_ARGUMENTS (fndecl));
!   poplevel (1, 0, 1);
!   BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
!
!   /* Generate rtl for function exit.  */
!   if (! flag_emit_class_files && ! flag_emit_xref)
      {
!       input_line = DECL_FUNCTION_LAST_LINE (fndecl);
!       expand_function_end ();
!
!       /* Run the optimizers and output assembler code for this function. */
!       rest_of_compilation (fndecl);
      }

!   current_function_decl = NULL_TREE;
    java_parser_context_restore_global ();
  }

--- 7364,7383 ----
       patched.  Dump it to a file if the user requested it.  */
    dump_java_tree (TDI_original, fndecl);

!   /* In unit-at-a-time mode, don't expand the method yet.  */
!   if (DECL_SAVED_TREE (fndecl) && flag_unit_at_a_time)
      {
!       cgraph_finalize_function (fndecl, DECL_SAVED_TREE (fndecl));
!       current_function_decl = NULL_TREE;
!       java_parser_context_restore_global ();
!       return;
      }

!   java_optimize_inline (fndecl);
!
!   /* Expand the function's body.  */
!   java_expand_body (fndecl);
!
    java_parser_context_restore_global ();
  }

*************** maybe_yank_clinit (tree mdecl)
*** 7862,7868 ****
  /* Install the argument from MDECL. Suitable to completion and
     expansion of mdecl's body.  */

! static void
  start_complete_expand_method (tree mdecl)
  {
    tree tem;
--- 7847,7853 ----
  /* Install the argument from MDECL. Suitable to completion and
     expansion of mdecl's body.  */

! void
  start_complete_expand_method (tree mdecl)
  {
    tree tem;
*************** java_expand_method_bodies (tree class)
*** 8005,8019 ****
    tree decl;
    for (decl = TYPE_METHODS (class); decl; decl = TREE_CHAIN (decl))
      {
!       if (!DECL_FUNCTION_BODY (decl))
  	continue;

        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
--- 7990,8015 ----
    tree decl;
    for (decl = TYPE_METHODS (class); decl; decl = TREE_CHAIN (decl))
      {
!       tree block;
!       tree body;
!
!       if (! DECL_FUNCTION_BODY (decl))
  	continue;

        current_function_decl = decl;

!       block = BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (decl));
!
!       if (TREE_CODE (block) != BLOCK)
! 	abort ();
!
!       /* Save the function body for inlining.  */
!       DECL_SAVED_TREE (decl) = block;
!
!       body = BLOCK_EXPR_BODY (block);
!
!       if (TREE_TYPE (body) == NULL_TREE)
! 	abort ();

        /* It's time to assign the variable flagging static class
  	 initialization based on which classes invoked static methods
*************** java_expand_method_bodies (tree class)
*** 8046,8060 ****
  	    }
  	}

!       /* Prepare the function for RTL expansion */
!       start_complete_expand_method (decl);

!       /* Expand function start, generate initialization flag
! 	 assignment, and handle synchronized methods. */
!       complete_start_java_method (decl);

!       /* Expand the rest of the function body and terminate
!          expansion. */
        source_end_java_method ();
      }
  }
--- 8042,8082 ----
  	    }
  	}

!       /* Prepend class initialization to static methods.  */
!       if (METHOD_STATIC (decl) && ! METHOD_PRIVATE (decl)
! 	  && ! flag_emit_class_files
! 	  && ! DECL_CLINIT_P (decl)
! 	  && ! CLASS_INTERFACE (TYPE_NAME (class)))
! 	{
! 	  tree init = build (CALL_EXPR, void_type_node,
! 			     build_address_of (soft_initclass_node),
! 			     build_tree_list (NULL_TREE,
! 					      build_class_ref (class)),
! 			     NULL_TREE);
! 	  TREE_SIDE_EFFECTS (init) = 1;
! 	  body = build (COMPOUND_EXPR, TREE_TYPE (body), init, body);
! 	  BLOCK_EXPR_BODY (block) = body;
! 	}
!
!       /* Wrap synchronized method bodies in a monitorenter
! 	 plus monitorexit cleanup.  */
!       if (METHOD_SYNCHRONIZED (decl) && ! flag_emit_class_files)
! 	{
! 	  tree enter, exit, lock;
! 	  if (METHOD_STATIC (decl))
! 	    lock = build_class_ref (class);
! 	  else
! 	    lock = DECL_ARGUMENTS (decl);
! 	  BUILD_MONITOR_ENTER (enter, lock);
! 	  BUILD_MONITOR_EXIT (exit, lock);

! 	  body = build (COMPOUND_EXPR, void_type_node,
! 			enter,
! 			build (TRY_FINALLY_EXPR, void_type_node, body, exit));
! 	  BLOCK_EXPR_BODY (block) = body;
! 	}

!       /* Expand the the function body.  */
        source_end_java_method ();
      }
  }
*************** java_complete_lhs (tree node)
*** 11541,11546 ****
--- 11563,11570 ----
  		      && TREE_CODE (wfl_op2) != DEFAULT_EXPR)
  		    unreachable_stmt_error (*ptr);
  		}
+ 	      if (TREE_TYPE (*ptr) == NULL_TREE)
+ 		TREE_TYPE (*ptr) = void_type_node;
  	      ptr = next;
  	    }
  	  *ptr = java_complete_tree (*ptr);
*************** patch_assignment (tree node, tree wfl_op
*** 12764,12769 ****
--- 12790,12796 ----
  	    tree block = build (BLOCK, TREE_TYPE (new_rhs), NULL);
  	    tree assignment
  	      = build (MODIFY_EXPR, TREE_TYPE (new_rhs), tmp, fold (new_rhs));
+ 	    DECL_CONTEXT (tmp) = current_function_decl;
  	    BLOCK_VARS (block) = tmp;
  	    BLOCK_EXPR_BODY (block)
  	      = build (COMPOUND_EXPR, TREE_TYPE (new_rhs), assignment, tmp);




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]