This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC 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]

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

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