This is the mail archive of the gcc-patches@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]

[basic-improvements] PATCH to make C++ return-in-memory semanticsexplicit


This patch follows on my recent changes to make C++
pass-by-invisible-reference semantics explicit in the tree structure, in
order to expose C++ semantics to tree optimizers.  It does this through a
flag on the CALL_EXPR, which tells expand_call and expand_call_inline to
treat the first argument as the structure value address.

There are a few tangential changes in this patch:

The change to maybe_set_unchanging seems to fix a thinko; I don't see any
good reason to treat decls with no DECL_INITIAL as unchanging.

The change to expand_expr improves generated code for functions which
return a struct in memory because of the processor ABI (as opposed to C++
semantics, like the rest of this patch).

The change to build_cplus_new causes us to stop building up AGGR_INIT_EXPRs
for classes that don't require a copy constructor; we don't need them,
since we can just bitwise copy such classes, and AFAICT
simplify_aggr_init_exprs_r wasn't actually copying the result into the
target slot, so anything which depended on reusing the slot would break.

Applied (soon) to basic-improvements-branch and tree-ssa-branch.

2002-12-13  Jason Merrill  <jason@redhat.com>

	* tree.h (CALL_EXPR_HAS_RETURN_SLOT_ADDR): New macro.
	* calls.c (expand_call): Handle it.
	* tree-inline.c (struct inline_data): Remove target_exprs field.
	(optimize_inline_calls): Don't initialize it.
	(expand_call_inline): Don't modify it.  Handle
	CALL_EXPR_HAS_RETURN_SLOT_ADDR.
	(declare_return_variable): Take return slot addr.
	* langhooks.h (copy_res_decl_for_inlining): Change target_exprs parm 
	to return_slot_addr.
	* langhooks-def.h, langhooks.c: Adjust.
	* explow.c (maybe_set_unchanging): Don't set RTX_UNCHANGING_P for
	a decl with no DECL_INITIAL.

	* expr.c (expand_expr): Don't discard the target of a call which
	returns in memory.

cp/
	* semantics.c (simplify_aggr_init_exprs_r): Also prepend the
	return slot for normal functions.  Set CALL_EXPR_HAS_RETURN_SLOT_ADDR.
	* tree.c (build_cplus_new): If the type isn't TREE_ADDRESSABLE,
	don't bother with an AGGR_INIT_EXPR.
	(cp_copy_res_decl_for_inlining): If the type isn't TREE_ADDRESSABLE,
	just generate a new decl normally.  Take return slot parm.
	* cp-tree.h: Adjust prototype.

*** ./cp/tree.c.~1~	Fri Dec 13 13:43:23 2002
--- ./cp/tree.c	Fri Dec 13 17:22:25 2002
*************** build_cplus_new (type, init)
*** 301,306 ****
--- 301,307 ----
    tree fn;
    tree slot;
    tree rval;
+   int is_ctor;
  
    /* Make sure that we're not trying to create an instance of an
       abstract class.  */
*************** build_cplus_new (type, init)
*** 309,314 ****
--- 310,320 ----
    if (TREE_CODE (init) != CALL_EXPR && TREE_CODE (init) != AGGR_INIT_EXPR)
      return convert (type, init);
  
+   fn = TREE_OPERAND (init, 0);
+   is_ctor = (TREE_CODE (fn) == ADDR_EXPR
+ 	     && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
+ 	     && DECL_CONSTRUCTOR_P (TREE_OPERAND (fn, 0)));
+ 
    slot = build (VAR_DECL, type);
    DECL_ARTIFICIAL (slot) = 1;
    DECL_CONTEXT (slot) = current_function_decl;
*************** build_cplus_new (type, init)
*** 322,334 ****
       replaces every AGGR_INIT_EXPR with a copy that uses a fresh
       temporary slot.  Then, expand_expr builds up a call-expression
       using the new slot.  */
!   fn = TREE_OPERAND (init, 0);
!   rval = build (AGGR_INIT_EXPR, type, fn, TREE_OPERAND (init, 1), slot);
!   TREE_SIDE_EFFECTS (rval) = 1;
!   AGGR_INIT_VIA_CTOR_P (rval) 
!     = (TREE_CODE (fn) == ADDR_EXPR
!        && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
!        && DECL_CONSTRUCTOR_P (TREE_OPERAND (fn, 0)));
    rval = build_target_expr (slot, rval);
  
    return rval;
--- 328,345 ----
       replaces every AGGR_INIT_EXPR with a copy that uses a fresh
       temporary slot.  Then, expand_expr builds up a call-expression
       using the new slot.  */
! 
!   /* If we don't need to use a constructor to create an object of this
!      type, don't mess with AGGR_INIT_EXPR.  */
!   if (is_ctor || TREE_ADDRESSABLE (type))
!     {
!       rval = build (AGGR_INIT_EXPR, type, fn, TREE_OPERAND (init, 1), slot);
!       TREE_SIDE_EFFECTS (rval) = 1;
!       AGGR_INIT_VIA_CTOR_P (rval) = is_ctor;
!     }
!   else
!     rval = init;
! 
    rval = build_target_expr (slot, rval);
  
    return rval;
*************** cp_auto_var_in_fn_p (var, fn)
*** 2313,2345 ****
  
  tree
  cp_copy_res_decl_for_inlining (result, fn, caller, decl_map_,
! 			       need_decl, target_exprs)
       tree result, fn, caller;
       void *decl_map_;
       int *need_decl;
!      void *target_exprs;
  {
    splay_tree decl_map = (splay_tree)decl_map_;
-   varray_type *texps = (varray_type *)target_exprs;
    tree var;
-   int aggregate_return_p;
  
!   /* Figure out whether or not FN returns an aggregate.  */
!   aggregate_return_p = IS_AGGR_TYPE (TREE_TYPE (result));
!   *need_decl = ! aggregate_return_p;
! 
!   /* If FN returns an aggregate then the caller will always create the
!      temporary (using a TARGET_EXPR) and the call will be the
!      initializing expression for the TARGET_EXPR.  If we were just to
       create a new VAR_DECL here, then the result of this function
       would be copied (bitwise) into the variable initialized by the
       TARGET_EXPR.  That's incorrect, so we must transform any
       references to the RESULT into references to the target.  */
!   if (aggregate_return_p)
      {
!       if (VARRAY_ACTIVE_SIZE (*texps) == 0)
! 	abort ();
!       var = TREE_OPERAND (VARRAY_TOP_TREE (*texps), 0);
        if (! same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (var),
  						       TREE_TYPE (result)))
  	abort ();
--- 2324,2355 ----
  
  tree
  cp_copy_res_decl_for_inlining (result, fn, caller, decl_map_,
! 			       need_decl, return_slot_addr)
       tree result, fn, caller;
       void *decl_map_;
       int *need_decl;
!      tree return_slot_addr;
  {
    splay_tree decl_map = (splay_tree)decl_map_;
    tree var;
  
!   /* If FN returns an aggregate then the caller will always pass the
!      address of the return slot explicitly.  If we were just to
       create a new VAR_DECL here, then the result of this function
       would be copied (bitwise) into the variable initialized by the
       TARGET_EXPR.  That's incorrect, so we must transform any
       references to the RESULT into references to the target.  */
! 
!   /* We should have an explicit return slot iff the return type is
!      TREE_ADDRESSABLE.  See simplify_aggr_init_expr.  */
!   if (TREE_ADDRESSABLE (TREE_TYPE (result))
!       != (return_slot_addr != NULL_TREE))
!     abort ();
! 
!   *need_decl = !return_slot_addr;
!   if (return_slot_addr)
      {
!       var = build_indirect_ref (return_slot_addr, "");
        if (! same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (var),
  						       TREE_TYPE (result)))
  	abort ();
*** ./cp/semantics.c.~1~	Fri Dec 13 13:43:22 2002
--- ./cp/semantics.c	Fri Dec 13 17:56:52 2002
*************** simplify_aggr_init_exprs_r (tp, walk_sub
*** 2190,2196 ****
    tree args;
    tree slot;
    tree type;
!   int copy_from_buffer_p;
  
    aggr_init_expr = *tp;
    /* We don't need to walk into types; there's nothing in a type that
--- 2190,2196 ----
    tree args;
    tree slot;
    tree type;
!   enum style_t { ctor, arg, pcc } style;
  
    aggr_init_expr = *tp;
    /* We don't need to walk into types; there's nothing in a type that
*************** simplify_aggr_init_exprs_r (tp, walk_sub
*** 2212,2259 ****
    args = TREE_OPERAND (aggr_init_expr, 1);
    slot = TREE_OPERAND (aggr_init_expr, 2);
    type = TREE_TYPE (aggr_init_expr);
    if (AGGR_INIT_VIA_CTOR_P (aggr_init_expr))
      {
!       /* Replace the first argument with the address of the third
! 	 argument to the AGGR_INIT_EXPR.  */
        cxx_mark_addressable (slot);
        args = tree_cons (NULL_TREE, 
  			build1 (ADDR_EXPR, 
  				build_pointer_type (TREE_TYPE (slot)),
  				slot),
! 			TREE_CHAIN (args));
      }
    call_expr = build (CALL_EXPR, 
  		     TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))),
  		     fn, args, NULL_TREE);
    TREE_SIDE_EFFECTS (call_expr) = 1;
  
!   /* If we're using the non-reentrant PCC calling convention, then we
!      need to copy the returned value out of the static buffer into the
!      SLOT.  */
!   copy_from_buffer_p = 0;
! #ifdef PCC_STATIC_STRUCT_RETURN  
!   if (!AGGR_INIT_VIA_CTOR_P (aggr_init_expr) && aggregate_value_p (type))
      {
        int old_ac = flag_access_control;
  
        flag_access_control = 0;
        call_expr = build_aggr_init (slot, call_expr,
  				   DIRECT_BIND | LOOKUP_ONLYCONVERTING);
        flag_access_control = old_ac;
-       copy_from_buffer_p = 1;
      }
- #endif
  
!   /* If this AGGR_INIT_EXPR indicates the value returned by a
!      function, then we want to use the value of the initialized
!      location as the result.  */
!   if (AGGR_INIT_VIA_CTOR_P (aggr_init_expr) || copy_from_buffer_p)
!     {
!       call_expr = build (COMPOUND_EXPR, type,
! 			 call_expr, slot);
!       TREE_SIDE_EFFECTS (call_expr) = 1;
!     }
  
    /* Replace the AGGR_INIT_EXPR with the CALL_EXPR.  */
    TREE_CHAIN (call_expr) = TREE_CHAIN (aggr_init_expr);
--- 2212,2277 ----
    args = TREE_OPERAND (aggr_init_expr, 1);
    slot = TREE_OPERAND (aggr_init_expr, 2);
    type = TREE_TYPE (aggr_init_expr);
+ 
    if (AGGR_INIT_VIA_CTOR_P (aggr_init_expr))
+     style = ctor;
+ #ifdef PCC_STATIC_STRUCT_RETURN
+   else if (1)
+     style = pcc;
+ #endif
+   else if (TREE_ADDRESSABLE (type))
+     style = arg;
+   else
+     /* We shouldn't build an AGGR_INIT_EXPR if we don't need any special
+        handling.  See build_cplus_new.  */
+     abort ();
+ 
+   if (style == ctor || style == arg)
      {
!       /* Pass the address of the slot.  If this is a constructor, we
! 	 replace the first argument; otherwise, we tack on a new one.  */
!       if (style == ctor)
! 	args = TREE_CHAIN (args);
! 
        cxx_mark_addressable (slot);
        args = tree_cons (NULL_TREE, 
  			build1 (ADDR_EXPR, 
  				build_pointer_type (TREE_TYPE (slot)),
  				slot),
! 			args);
      }
+ 
    call_expr = build (CALL_EXPR, 
  		     TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))),
  		     fn, args, NULL_TREE);
    TREE_SIDE_EFFECTS (call_expr) = 1;
  
!   if (style == arg)
      {
+       /* Tell the backend that we've added our return slot to the argument
+ 	 list.  */
+       CALL_EXPR_HAS_RETURN_SLOT_ADDR (call_expr) = 1;
+       /* And don't let anyone use the value of the call directly in a
+ 	 larger expression.  */
+       TREE_TYPE (call_expr) = void_type_node;
+     }
+   else if (style == pcc)
+     {
+       /* If we're using the non-reentrant PCC calling convention, then we
+ 	 need to copy the returned value out of the static buffer into the
+ 	 SLOT.  */
        int old_ac = flag_access_control;
  
        flag_access_control = 0;
        call_expr = build_aggr_init (slot, call_expr,
  				   DIRECT_BIND | LOOKUP_ONLYCONVERTING);
        flag_access_control = old_ac;
      }
  
!   /* We want to use the value of the initialized location as the
!      result.  */
!   call_expr = build (COMPOUND_EXPR, type,
! 		     call_expr, slot);
  
    /* Replace the AGGR_INIT_EXPR with the CALL_EXPR.  */
    TREE_CHAIN (call_expr) = TREE_CHAIN (aggr_init_expr);
*** ./cp/cp-tree.h.~1~	Fri Dec 13 13:43:16 2002
--- ./cp/cp-tree.h	Fri Dec 13 14:52:12 2002
*************** extern tree cp_add_pending_fn_decls PARA
*** 4304,4310 ****
  extern int cp_is_overload_p PARAMS ((tree));
  extern int cp_auto_var_in_fn_p PARAMS ((tree,tree));
  extern tree cp_copy_res_decl_for_inlining PARAMS ((tree, tree, tree, void*,
! 						   int*, void*));
  extern int cp_start_inlining			PARAMS ((tree));
  extern void cp_end_inlining			PARAMS ((tree));
  
--- 4304,4310 ----
  extern int cp_is_overload_p PARAMS ((tree));
  extern int cp_auto_var_in_fn_p PARAMS ((tree,tree));
  extern tree cp_copy_res_decl_for_inlining PARAMS ((tree, tree, tree, void*,
! 						   int*, tree));
  extern int cp_start_inlining			PARAMS ((tree));
  extern void cp_end_inlining			PARAMS ((tree));
  
*** ./calls.c.~1~	Fri Dec 13 13:40:44 2002
--- ./calls.c	Fri Dec 13 17:56:00 2002
*************** expand_call (exp, target, ignore)
*** 2248,2254 ****
        {
  	struct_value_size = int_size_in_bytes (TREE_TYPE (exp));
  
! 	if (target && GET_CODE (target) == MEM)
  	  structure_value_addr = XEXP (target, 0);
  	else
  	  {
--- 2248,2257 ----
        {
  	struct_value_size = int_size_in_bytes (TREE_TYPE (exp));
  
! 	if (CALL_EXPR_HAS_RETURN_SLOT_ADDR (exp))
! 	  /* The structure value address arg is already in actparms.  */
! 	  structure_value_addr_parm = 1;
! 	else if (target && GET_CODE (target) == MEM)
  	  structure_value_addr = XEXP (target, 0);
  	else
  	  {
*** ./tree.h.~1~	Fri Dec 13 13:41:26 2002
--- ./tree.h	Fri Dec 13 14:52:12 2002
*************** struct tree_common GTY(())
*** 202,207 ****
--- 202,209 ----
             TREE_LIST or TREE_VEC
         TREE_PRIVATE in
             ..._DECL
+        CALL_EXPR_HAS_RETURN_SLOT_ADDR in
+            CALL_EXPR
  
     protected_flag:
  
*************** extern void tree_vec_elt_check_failed PA
*** 638,643 ****
--- 640,649 ----
     an exception.  In a CALL_EXPR, nonzero means the call cannot throw.  */
  #define TREE_NOTHROW(NODE) ((NODE)->common.nothrow_flag)
  
+ /* In a CALL_EXPR, means that the address of the return slot is part of the
+    argument list.  */
+ #define CALL_EXPR_HAS_RETURN_SLOT_ADDR(NODE) ((NODE)->common.private_flag)
+ 
  /* In a type, nonzero means that all objects of the type are guaranteed by the
     language or front-end to be properly aligned, so we can indicate that a MEM
     of this type is aligned at least to the alignment of the type, even if it
*** ./tree-inline.c.~1~	Fri Dec 13 13:41:25 2002
--- ./tree-inline.c	Fri Dec 13 14:52:12 2002
*************** typedef struct inline_data
*** 90,97 ****
    /* Nonzero if we are currently within the cleanup for a
       TARGET_EXPR.  */
    int in_target_cleanup_p;
-   /* A stack of the TARGET_EXPRs that we are currently processing.  */
-   varray_type target_exprs;
    /* A list of the functions current function has inlined.  */
    varray_type inlined_fns;
    /* The approximate number of statements we have inlined in the
--- 90,95 ----
*************** typedef struct inline_data
*** 109,115 ****
  
  /* Prototypes.  */
  
! static tree declare_return_variable PARAMS ((inline_data *, tree *));
  static tree copy_body_r PARAMS ((tree *, int *, void *));
  static tree copy_body PARAMS ((inline_data *));
  static tree expand_call_inline PARAMS ((tree *, int *, void *));
--- 107,113 ----
  
  /* Prototypes.  */
  
! static tree declare_return_variable PARAMS ((inline_data *, tree, tree *));
  static tree copy_body_r PARAMS ((tree *, int *, void *));
  static tree copy_body PARAMS ((inline_data *));
  static tree expand_call_inline PARAMS ((tree *, int *, void *));
*************** initialize_inlined_parameters (id, args,
*** 779,791 ****
  
  #ifndef INLINER_FOR_JAVA
  static tree
! declare_return_variable (id, use_stmt)
       struct inline_data *id;
       tree *use_stmt;
  #else /* INLINER_FOR_JAVA */
  static tree
! declare_return_variable (id, var)
       struct inline_data *id;
       tree *var;
  #endif /* INLINER_FOR_JAVA */
  {
--- 777,791 ----
  
  #ifndef INLINER_FOR_JAVA
  static tree
! declare_return_variable (id, return_slot_addr, use_stmt)
       struct inline_data *id;
+      tree return_slot_addr;
       tree *use_stmt;
  #else /* INLINER_FOR_JAVA */
  static tree
! declare_return_variable (id, return_slot_addr, var)
       struct inline_data *id;
+      tree return_slot_addr;
       tree *var;
  #endif /* INLINER_FOR_JAVA */
  {
*************** declare_return_variable (id, var)
*** 811,817 ****
  #ifndef 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, &id->target_exprs));
  
    /* Register the VAR_DECL as the equivalent for the RESULT_DECL; that
       way, when the RESULT_DECL is encountered, it will be
--- 811,817 ----
  #ifndef 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, return_slot_addr));
  
    /* Register the VAR_DECL as the equivalent for the RESULT_DECL; that
       way, when the RESULT_DECL is encountered, it will be
*************** declare_return_variable (id, var)
*** 837,843 ****
  #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,
--- 837,843 ----
  #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, return_slot_addr));
  
    splay_tree_insert (id->decl_map,
  		     (splay_tree_key) result,
*************** expand_call_inline (tp, walk_subtrees, d
*** 1025,1030 ****
--- 1025,1032 ----
    tree arg_inits;
    tree *inlined_body;
    splay_tree st;
+   tree args;
+   tree return_slot_addr;
  
    /* See what we've got.  */
    id = (inline_data *) data;
*************** expand_call_inline (tp, walk_subtrees, d
*** 1040,1048 ****
        /* We're walking our own subtrees.  */
        *walk_subtrees = 0;
  
-       /* Push *TP on the stack of pending TARGET_EXPRs.  */
-       VARRAY_PUSH_TREE (id->target_exprs, *tp);
- 
        /* Actually walk over them.  This loop is the body of
  	 walk_trees, omitting the case where the TARGET_EXPR
  	 itself is handled.  */
--- 1042,1047 ----
*************** expand_call_inline (tp, walk_subtrees, d
*** 1056,1064 ****
  	    --id->in_target_cleanup_p;
  	}
  
-       /* We're done with this TARGET_EXPR now.  */
-       VARRAY_POP (id->target_exprs);
- 
        return NULL_TREE;
  #else /* INLINER_FOR_JAVA */
        abort ();
--- 1055,1060 ----
*************** expand_call_inline (tp, walk_subtrees, d
*** 1134,1141 ****
  				 NULL, NULL);
  
    /* 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
       push FN on the stack of functions we are inlining; we want to
       inline calls to FN that appear in the initializers for the
--- 1130,1145 ----
  				 NULL, NULL);
  
    /* Initialize the parameters.  */
+   args = TREE_OPERAND (t, 1);
+   return_slot_addr = NULL_TREE;
+   if (CALL_EXPR_HAS_RETURN_SLOT_ADDR (t))
+     {
+       return_slot_addr = TREE_VALUE (args);
+       args = TREE_CHAIN (args);
+     }
+ 
  #ifndef INLINER_FOR_JAVA
!   arg_inits = initialize_inlined_parameters (id, args, fn);
    /* 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
*************** expand_call_inline (tp, walk_subtrees, d
*** 1144,1150 ****
    /* 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
--- 1148,1154 ----
    /* 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, args, fn, expr);
    if (arg_inits)
      {
        /* Expand any inlined calls in the initializers.  Do this before we
*************** expand_call_inline (tp, walk_subtrees, d
*** 1205,1215 ****
    /* Declare the return variable for the function.  */
    COMPOUND_BODY (stmt)
      = 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);
--- 1209,1219 ----
    /* Declare the return variable for the function.  */
    COMPOUND_BODY (stmt)
      = chainon (COMPOUND_BODY (stmt),
! 	       declare_return_variable (id, return_slot_addr, &use_stmt));
  #else /* INLINER_FOR_JAVA */
    {
      /* Declare the return variable for the function.  */
!     tree decl = declare_return_variable (id, return_slot_addr, &retvar);
      if (retvar)
        {
  	tree *next = &BLOCK_VARS (expr);
*************** optimize_inline_calls (fn)
*** 1377,1385 ****
    prev_fn = ((*lang_hooks.tree_inlining.add_pending_fn_decls)
  	     (&id.fns, prev_fn));
  
-   /* Create the stack of TARGET_EXPRs.  */
-   VARRAY_TREE_INIT (id.target_exprs, 32, "target_exprs");
- 
    /* Create the list of functions this call will inline.  */
    VARRAY_TREE_INIT (id.inlined_fns, 32, "inlined_fns");
  
--- 1381,1386 ----
*** ./langhooks.h.~1~	Mon Oct 28 14:47:06 2002
--- ./langhooks.h	Fri Dec 13 14:52:12 2002
*************** struct lang_hooks_for_tree_inlining
*** 48,54 ****
  							  union tree_node *,
  							  union tree_node *,
  							  void *, int *,
! 							  void *));
    int (*anon_aggr_type_p) PARAMS ((union tree_node *));
    bool (*var_mod_type_p) PARAMS ((union tree_node *));
    int (*start_inlining) PARAMS ((union tree_node *));
--- 48,54 ----
  							  union tree_node *,
  							  union tree_node *,
  							  void *, int *,
! 							  tree));
    int (*anon_aggr_type_p) PARAMS ((union tree_node *));
    bool (*var_mod_type_p) PARAMS ((union tree_node *));
    int (*start_inlining) PARAMS ((union tree_node *));
*** ./langhooks.c.~1~	Fri Dec 13 13:41:08 2002
--- ./langhooks.c	Fri Dec 13 14:52:12 2002
*************** lhd_tree_inlining_auto_var_in_fn_p (var,
*** 356,368 ****
  
  tree
  lhd_tree_inlining_copy_res_decl_for_inlining (res, fn, caller,
! 					      dm, ndp, texps)
       tree res, fn, caller;
       void *dm ATTRIBUTE_UNUSED;
       int *ndp ATTRIBUTE_UNUSED;
!      void *texps ATTRIBUTE_UNUSED;
  {
!   return copy_decl_for_inlining (res, fn, caller);
  }
  
  /* lang_hooks.tree_inlining.anon_aggr_type_p determines whether T is a
--- 356,372 ----
  
  tree
  lhd_tree_inlining_copy_res_decl_for_inlining (res, fn, caller,
! 					      dm, ndp, return_slot_addr)
       tree res, fn, caller;
       void *dm ATTRIBUTE_UNUSED;
       int *ndp ATTRIBUTE_UNUSED;
!      tree return_slot_addr ATTRIBUTE_UNUSED;
  {
!   if (return_slot_addr)
!     return build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (return_slot_addr)),
! 		   return_slot_addr);
!   else
!     return copy_decl_for_inlining (res, fn, caller);
  }
  
  /* lang_hooks.tree_inlining.anon_aggr_type_p determines whether T is a
*** ./langhooks-def.h.~1~	Fri Dec 13 13:41:08 2002
--- ./langhooks-def.h	Fri Dec 13 14:52:12 2002
*************** int lhd_tree_inlining_tree_chain_matters
*** 76,82 ****
  int lhd_tree_inlining_auto_var_in_fn_p		PARAMS ((tree, tree));
  tree lhd_tree_inlining_copy_res_decl_for_inlining PARAMS ((tree, tree,
  							   tree, void *,
! 							   int *, void *));
  int lhd_tree_inlining_anon_aggr_type_p		PARAMS ((tree));
  int lhd_tree_inlining_start_inlining		PARAMS ((tree));
  void lhd_tree_inlining_end_inlining		PARAMS ((tree));
--- 76,82 ----
  int lhd_tree_inlining_auto_var_in_fn_p		PARAMS ((tree, tree));
  tree lhd_tree_inlining_copy_res_decl_for_inlining PARAMS ((tree, tree,
  							   tree, void *,
! 							   int *, tree));
  int lhd_tree_inlining_anon_aggr_type_p		PARAMS ((tree));
  int lhd_tree_inlining_start_inlining		PARAMS ((tree));
  void lhd_tree_inlining_end_inlining		PARAMS ((tree));
*** ./explow.c.~1~	Fri Dec 13 13:40:55 2002
--- ./explow.c	Fri Dec 13 16:35:40 2002
*************** maybe_set_unchanging (ref, t)
*** 660,667 ****
       first case, and decls with TREE_CONSTANT initializers in the second.  */
    if ((TREE_READONLY (t) && DECL_P (t)
         && (TREE_CODE (t) == PARM_DECL
! 	   || DECL_INITIAL (t) == NULL_TREE
! 	   || TREE_CONSTANT (DECL_INITIAL (t))))
        || TREE_CODE_CLASS (TREE_CODE (t)) == 'c')
      RTX_UNCHANGING_P (ref) = 1;
  }
--- 660,666 ----
       first case, and decls with TREE_CONSTANT initializers in the second.  */
    if ((TREE_READONLY (t) && DECL_P (t)
         && (TREE_CODE (t) == PARM_DECL
! 	   || (DECL_INITIAL (t) && TREE_CONSTANT (DECL_INITIAL (t)))))
        || TREE_CODE_CLASS (TREE_CODE (t)) == 'c')
      RTX_UNCHANGING_P (ref) = 1;
  }
*** ./expr.c.~1~	Fri Dec 13 13:40:55 2002
--- ./expr.c	Fri Dec 13 16:35:40 2002
*************** expand_expr (exp, target, tmode, modifie
*** 6552,6563 ****
    /* If will do cse, generate all results into pseudo registers
       since 1) that allows cse to find more things
       and 2) otherwise cse could produce an insn the machine
!      cannot support.  And exception is a CONSTRUCTOR into a multi-word
!      MEM: that's much more likely to be most efficient into the MEM.  */
  
    if (! cse_not_expected && mode != BLKmode && target
        && (GET_CODE (target) != REG || REGNO (target) < FIRST_PSEUDO_REGISTER)
!       && ! (code == CONSTRUCTOR && GET_MODE_SIZE (mode) > UNITS_PER_WORD))
      target = subtarget;
  
    switch (code)
--- 6552,6565 ----
    /* If will do cse, generate all results into pseudo registers
       since 1) that allows cse to find more things
       and 2) otherwise cse could produce an insn the machine
!      cannot support.  An exception is a CONSTRUCTOR into a multi-word
!      MEM: that's much more likely to be most efficient into the MEM.
!      Another is a CALL_EXPR which must return in memory.  */
  
    if (! cse_not_expected && mode != BLKmode && target
        && (GET_CODE (target) != REG || REGNO (target) < FIRST_PSEUDO_REGISTER)
!       && ! (code == CONSTRUCTOR && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
!       && ! (code == CALL_EXPR && aggregate_value_p (exp)))
      target = subtarget;
  
    switch (code)

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