simple calls.c cleanups

Jan Hubicka hubicka@atrey.karlin.mff.cuni.cz
Thu Mar 30 03:48:00 GMT 2000


Hi
This code contains simple cleanups. It breaks out the attributes detection
and code integration from expand_call as well as convert number of variables
to flags (this simplifies function calling at some places too).

While implementing it I found that we don't support nothrow and malloc
attributes at the fuction types.  Is that some kind of design decision
or just omision?
I think all attributes allowed for functions ought to be useable for
indirect calls too.

Honza

Wed Mar 29 21:32:33 CEST 2000  Jan Hubicka  <jh@suse.cz>
	* calls.c (ECF_MALLOC, ECF_MAY_BE_ALLOCA, ECF_RETURNS_TWICE,
	 ECF_LONGJMP, ECF_FORK_OR_EXEC):  New constants.
	(ECF_IS_CONST): Rename to ECF_CONST.
	(special_function_p): Make static, change interface.
	(flags_from_decl_or_type, try_to_integrate): Break out from ...
	(expand_call) ... here; convert number of variables to flags.
	(emit_library_call_vlue_1): Likewise.
	(setjmp_call_p): New function.
	(initialize_argument_information): Accepts flags as argument;
	return flags.
	(precompute_arguments): Likewise.
	* tree.h (special_function_p): Remove.
	(setjmp_call_p): Add prototype.

Wed Mar 29 21:37:22 CEST 2000  Jan Hubicka  <jh@suse.cz>
	* optimize.c (calls_setjmp_p):  Use setjmp_call_p instead of
	special_function_p.
	
*** tree.h.ooo	Wed Mar 29 20:26:10 2000
--- tree.h	Wed Mar 29 21:03:13 2000
*************** extern struct rtx_def *emit_line_note		P
*** 2543,2550 ****
  extern struct rtx_def *emit_line_note_force	PARAMS ((const char *, int));
  
  /* In calls.c */
! extern void special_function_p	        PARAMS ((tree, int *, int *,
! 						int *, int *, int *));
  
  /* In c-typeck.c */
  extern int mark_addressable		PARAMS ((tree));
--- 2543,2551 ----
  extern struct rtx_def *emit_line_note_force	PARAMS ((const char *, int));
  
  /* In calls.c */
! 
! /* Flags used by special_function_p.  */
! extern int setjmp_call_p		PARAMS ((tree));
  
  /* In c-typeck.c */
  extern int mark_addressable		PARAMS ((tree));
*** cp/optimize.c.ooo	Wed Mar 29 20:57:39 2000
--- cp/optimize.c	Wed Mar 29 21:03:05 2000
*************** calls_setjmp_r (tp, walk_subtrees, data)
*** 758,767 ****
    if (TREE_CODE (*tp) != FUNCTION_DECL)
      return NULL_TREE;
  
!   special_function_p (*tp, &setjmp_p, &longjmp_p, &fork_or_exec_p, &malloc_p,
! 		      &alloca_p);
! 
!   return setjmp_p ? *tp : NULL_TREE;
  }
  
  /* Returns non-zero if FN calls `setjmp' or some other function that
--- 758,764 ----
    if (TREE_CODE (*tp) != FUNCTION_DECL)
      return NULL_TREE;
  
!   return setjmp_call_p (tp);
  }
  
  /* Returns non-zero if FN calls `setjmp' or some other function that
*** calls.c.ooo	Wed Mar 29 20:09:09 2000
--- calls.c	Wed Mar 29 21:39:12 2000
*************** int stack_arg_under_construction;
*** 150,158 ****
  static int calls_function	PARAMS ((tree, int));
  static int calls_function_1	PARAMS ((tree, int));
  
! #define ECF_IS_CONST		1
! #define ECF_NOTHROW		2
! #define ECF_SIBCALL		4
  static void emit_call_1		PARAMS ((rtx, tree, tree, HOST_WIDE_INT,
  					 HOST_WIDE_INT, HOST_WIDE_INT, rtx,
  					 rtx, int, rtx, int));
--- 150,174 ----
  static int calls_function	PARAMS ((tree, int));
  static int calls_function_1	PARAMS ((tree, int));
  
! /* Nonzero if this is a call to a `const' function. */
! #define ECF_CONST		1
! /* Nonzero if this is a call to a `volatile' function.  */
! #define ECF_NORETURN		2
! /* Nonzero if this is a call to malloc or a related function. */
! #define ECF_MALLOC		4
! /* Nonzero if it is plausible that this is a call to alloca.  */
! #define ECF_MAY_BE_ALLOCA	8
! /* Nonzero if this is a call to a function that won't throw an exception.  */
! #define ECF_NOTHROW		16
! /* Nonzero if this is a call to setjmp or a related function.  */
! #define ECF_RETURNS_TWICE	32
! /* Nonzero if this is a call to `longjmp'.  */
! #define ECF_LONGJMP		64
! /* Nonzero if this is a syscall that makes a new process in the image of
!    the current one.  */
! #define ECF_FORK_OR_EXEC	128
! #define ECF_SIBCALL		256
! 
  static void emit_call_1		PARAMS ((rtx, tree, tree, HOST_WIDE_INT,
  					 HOST_WIDE_INT, HOST_WIDE_INT, rtx,
  					 rtx, int, rtx, int));
*************** static int libfunc_nothrow			PARAMS ((rt
*** 188,193 ****
--- 204,213 ----
  static rtx emit_library_call_value_1 		PARAMS ((int, rtx, rtx, int,
  							 enum machine_mode,
  							 int, va_list));
+ static int special_function_p			PARAMS ((tree, int));
+ static int flags_from_decl_or_type 		PARAMS ((tree));
+ static rtx try_to_integrate			PARAMS ((tree, tree, rtx,
+ 							 int, tree, rtx));
  
  #ifdef REG_PARM_STACK_SPACE
  static rtx save_fixed_argument_area	PARAMS ((int, rtx, int *, int *));
*************** prepare_call_address (funexp, fndecl, ca
*** 401,409 ****
     We restore `inhibit_defer_pop' to that value.
  
     CALL_FUSAGE is either empty or an EXPR_LIST of USE expressions that
!    denote registers used by the called function.
! 
!    IS_CONST is true if this is a `const' call.  */
  
  static void
  emit_call_1 (funexp, fndecl, funtype, stack_size, rounded_stack_size,
--- 421,427 ----
     We restore `inhibit_defer_pop' to that value.
  
     CALL_FUSAGE is either empty or an EXPR_LIST of USE expressions that
!    denote registers used by the called function.  */
  
  static void
  emit_call_1 (funexp, fndecl, funtype, stack_size, rounded_stack_size,
*************** emit_call_1 (funexp, fndecl, funtype, st
*** 553,559 ****
      CALL_INSN_FUNCTION_USAGE (call_insn) = call_fusage;
  
    /* If this is a const call, then set the insn's unchanging bit.  */
!   if (ecf_flags & ECF_IS_CONST)
      CONST_CALL_P (call_insn) = 1;
  
    /* If this call can't throw, attach a REG_EH_REGION reg note to that
--- 571,577 ----
      CALL_INSN_FUNCTION_USAGE (call_insn) = call_fusage;
  
    /* If this is a const call, then set the insn's unchanging bit.  */
!   if (ecf_flags & ECF_CONST)
      CONST_CALL_P (call_insn) = 1;
  
    /* If this call can't throw, attach a REG_EH_REGION reg note to that
*************** emit_call_1 (funexp, fndecl, funtype, st
*** 595,601 ****
        if (rounded_stack_size != 0)
  	{
  	  if (flag_defer_pop && inhibit_defer_pop == 0
! 	      && !(ecf_flags & ECF_IS_CONST))
  	    pending_stack_adjust += rounded_stack_size;
  	  else
  	    adjust_stack (rounded_stack_size_rtx);
--- 613,619 ----
        if (rounded_stack_size != 0)
  	{
  	  if (flag_defer_pop && inhibit_defer_pop == 0
! 	      && !(ecf_flags & ECF_CONST))
  	    pending_stack_adjust += rounded_stack_size;
  	  else
  	    adjust_stack (rounded_stack_size_rtx);
*************** emit_call_1 (funexp, fndecl, funtype, st
*** 622,654 ****
     For example, if the function might return more than one time (setjmp), then
     set RETURNS_TWICE to a nonzero value.
  
!    Similarly set IS_LONGJMP for if the function is in the longjmp family.
  
!    Set IS_MALLOC for any of the standard memory allocation functions which
     allocate from the heap.
  
     Set MAY_BE_ALLOCA for any memory allocation function that might allocate
     space from the stack such as alloca.  */
  
! void
! special_function_p (fndecl, returns_twice, is_longjmp, fork_or_exec,
! 		    is_malloc, may_be_alloca)
       tree fndecl;
!      int *returns_twice;
!      int *is_longjmp;
!      int *fork_or_exec;
!      int *is_malloc;
!      int *may_be_alloca;
! {
!   *returns_twice = 0;
!   *is_longjmp = 0;
!   *fork_or_exec = 0;
!   *may_be_alloca = 0;
! 
!   /* The function decl may have the `malloc' attribute.  */
!   *is_malloc = fndecl && DECL_IS_MALLOC (fndecl);
! 
!   if (! *is_malloc 
        && fndecl && DECL_NAME (fndecl)
        && IDENTIFIER_LENGTH (DECL_NAME (fndecl)) <= 17
        /* Exclude functions not at the file scope, or not `extern',
--- 640,659 ----
     For example, if the function might return more than one time (setjmp), then
     set RETURNS_TWICE to a nonzero value.
  
!    Similarly set LONGJMP for if the function is in the longjmp family.
  
!    Set MALLOC for any of the standard memory allocation functions which
     allocate from the heap.
  
     Set MAY_BE_ALLOCA for any memory allocation function that might allocate
     space from the stack such as alloca.  */
  
! static int
! special_function_p (fndecl, flags)
       tree fndecl;
!      int flags;
! {
!   if (! (flags & ECF_MALLOC)
        && fndecl && DECL_NAME (fndecl)
        && IDENTIFIER_LENGTH (DECL_NAME (fndecl)) <= 17
        /* Exclude functions not at the file scope, or not `extern',
*************** special_function_p (fndecl, returns_twic
*** 662,674 ****
        /* We assume that alloca will always be called by name.  It
  	 makes no sense to pass it as a pointer-to-function to
  	 anything that does not understand its behavior.  */
!       *may_be_alloca
! 	= (((IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 6
! 	     && name[0] == 'a'
! 	     && ! strcmp (name, "alloca"))
! 	    || (IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 16
! 		&& name[0] == '_'
! 		&& ! strcmp (name, "__builtin_alloca"))));
  
        /* Disregard prefix _, __ or __x.  */
        if (name[0] == '_')
--- 667,679 ----
        /* We assume that alloca will always be called by name.  It
  	 makes no sense to pass it as a pointer-to-function to
  	 anything that does not understand its behavior.  */
!       if (((IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 6
! 	    && name[0] == 'a'
! 	    && ! strcmp (name, "alloca"))
! 	   || (IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 16
! 	       && name[0] == '_'
! 	       && ! strcmp (name, "__builtin_alloca"))))
! 	flags |= ECF_MAY_BE_ALLOCA;
  
        /* Disregard prefix _, __ or __x.  */
        if (name[0] == '_')
*************** special_function_p (fndecl, returns_twic
*** 683,709 ****
  
        if (tname[0] == 's')
  	{
! 	  *returns_twice
! 	     = ((tname[1] == 'e'
! 		 && (! strcmp (tname, "setjmp")
! 		     || ! strcmp (tname, "setjmp_syscall")))
! 	        || (tname[1] == 'i'
! 		    && ! strcmp (tname, "sigsetjmp"))
! 	        || (tname[1] == 'a'
! 		    && ! strcmp (tname, "savectx")));
  	  if (tname[1] == 'i'
  	      && ! strcmp (tname, "siglongjmp"))
! 	    *is_longjmp = 1;
  	}
        else if ((tname[0] == 'q' && tname[1] == 's'
  		&& ! strcmp (tname, "qsetjmp"))
  	       || (tname[0] == 'v' && tname[1] == 'f'
  		   && ! strcmp (tname, "vfork")))
! 	*returns_twice = 1;
  
        else if (tname[0] == 'l' && tname[1] == 'o'
  	       && ! strcmp (tname, "longjmp"))
! 	*is_longjmp = 1;
  
        else if ((tname[0] == 'f' && tname[1] == 'o'
  		&& ! strcmp (tname, "fork"))
--- 688,715 ----
  
        if (tname[0] == 's')
  	{
! 	  if ((tname[1] == 'e'
! 	       && (! strcmp (tname, "setjmp")
! 		   || ! strcmp (tname, "setjmp_syscall")))
! 	      || (tname[1] == 'i'
! 		  && ! strcmp (tname, "sigsetjmp"))
! 	      || (tname[1] == 'a'
! 		  && ! strcmp (tname, "savectx")))
! 	    flags |= ECF_RETURNS_TWICE;
! 
  	  if (tname[1] == 'i'
  	      && ! strcmp (tname, "siglongjmp"))
! 	    flags |= ECF_LONGJMP;
  	}
        else if ((tname[0] == 'q' && tname[1] == 's'
  		&& ! strcmp (tname, "qsetjmp"))
  	       || (tname[0] == 'v' && tname[1] == 'f'
  		   && ! strcmp (tname, "vfork")))
! 	flags |= ECF_RETURNS_TWICE;
  
        else if (tname[0] == 'l' && tname[1] == 'o'
  	       && ! strcmp (tname, "longjmp"))
! 	flags |= ECF_LONGJMP;
  
        else if ((tname[0] == 'f' && tname[1] == 'o'
  		&& ! strcmp (tname, "fork"))
*************** special_function_p (fndecl, returns_twic
*** 717,723 ****
  		   && (tname[5] == '\0'
  		       || ((tname[5] == 'p' || tname[5] == 'e')
  			   && tname[6] == '\0'))))
! 	*fork_or_exec = 1;
  
        /* Do not add any more malloc-like functions to this list,
           instead mark them as malloc functions using the malloc attribute.
--- 723,729 ----
  		   && (tname[5] == '\0'
  		       || ((tname[5] == 'p' || tname[5] == 'e')
  			   && tname[6] == '\0'))))
! 	flags |= ECF_FORK_OR_EXEC;
  
        /* Do not add any more malloc-like functions to this list,
           instead mark them as malloc functions using the malloc attribute.
*************** special_function_p (fndecl, returns_twic
*** 730,739 ****
  	       && (! strcmp (tname, "malloc")
  		   || ! strcmp (tname, "calloc")
  		   || ! strcmp (tname, "strdup")))
! 	*is_malloc = 1;
      }
  }
  
  /* Precompute all register parameters as described by ARGS, storing values
     into fields within the ARGS array.
  
--- 736,781 ----
  	       && (! strcmp (tname, "malloc")
  		   || ! strcmp (tname, "calloc")
  		   || ! strcmp (tname, "strdup")))
! 	flags |= ECF_MALLOC;
!     }
!   return flags;
! }
! 
! /* Return nonzero when tree represent call to longjmp.  */
! int
! setjmp_call_p (fndecl)
!      tree fndecl;
! {
!   return special_function_p (fndecl, 0) & ECF_RETURNS_TWICE;
! }
! 
! /* Detect flags (function attributes) from the function type node.  */
! static int
! flags_from_decl_or_type (exp)
!      tree exp;
! {
!   int flags = 0;
!   /* ??? We can't set IS_MALLOC for function types?  */
!   if (DECL_P (exp))
!     {
!       /* The function exp may have the `malloc' attribute.  */
!       if (DECL_P (exp) && DECL_IS_MALLOC (exp))
! 	flags |= ECF_MALLOC;
! 
!       if (TREE_NOTHROW (exp))
! 	flags |= ECF_NOTHROW;
      }
+ 
+   if (TREE_READONLY (exp) && !TREE_THIS_VOLATILE (exp))
+     flags |= ECF_CONST;
+ 
+   if (TREE_THIS_VOLATILE (exp))
+     flags |= ECF_NORETURN;
+ 
+   return flags;
  }
  
+ 
  /* Precompute all register parameters as described by ARGS, storing values
     into fields within the ARGS array.
  
*************** store_unaligned_arguments_into_pseudos (
*** 996,1009 ****
     OLD_STACK_LEVEL is a pointer to an rtx which olds the old stack level
     and may be modified by this routine.
  
!    OLD_PENDING_ADJ, MUST_PREALLOCATE and IS_CONST are pointers to integer
     flags which may may be modified by this routine.  */
  
  static void
  initialize_argument_information (num_actuals, args, args_size, n_named_args,
  				 actparms, fndecl, args_so_far,
  				 reg_parm_stack_space, old_stack_level,
! 				 old_pending_adj, must_preallocate, is_const,
  				 ecf_flags)
       int num_actuals ATTRIBUTE_UNUSED;
       struct arg_data *args;
--- 1038,1051 ----
     OLD_STACK_LEVEL is a pointer to an rtx which olds the old stack level
     and may be modified by this routine.
  
!    OLD_PENDING_ADJ, MUST_PREALLOCATE and FLAGS are pointers to integer
     flags which may may be modified by this routine.  */
  
  static void
  initialize_argument_information (num_actuals, args, args_size, n_named_args,
  				 actparms, fndecl, args_so_far,
  				 reg_parm_stack_space, old_stack_level,
! 				 old_pending_adj, must_preallocate, flags,
  				 ecf_flags)
       int num_actuals ATTRIBUTE_UNUSED;
       struct arg_data *args;
*************** initialize_argument_information (num_act
*** 1016,1023 ****
       rtx *old_stack_level;
       int *old_pending_adj;
       int *must_preallocate;
!      int *is_const;
!      int ecf_flags;
  {
    /* 1 if scanning parms front to back, -1 if scanning back to front.  */
    int inc;
--- 1058,1065 ----
       rtx *old_stack_level;
       int *old_pending_adj;
       int *must_preallocate;
!      int *flags;
!      int ecf_flags ATTRIBUTE_UNUSED;
  {
    /* 1 if scanning parms front to back, -1 if scanning back to front.  */
    int inc;
*************** initialize_argument_information (num_act
*** 1160,1166 ****
  	      MEM_SET_IN_STRUCT_P (copy, AGGREGATE_TYPE_P (type));
  
  	      store_expr (args[i].tree_value, copy, 0);
! 	      *is_const = 0;
  
  	      args[i].tree_value = build1 (ADDR_EXPR,
  					   build_pointer_type (type),
--- 1202,1208 ----
  	      MEM_SET_IN_STRUCT_P (copy, AGGREGATE_TYPE_P (type));
  
  	      store_expr (args[i].tree_value, copy, 0);
! 	      *flags &= ~ECF_CONST;
  
  	      args[i].tree_value = build1 (ADDR_EXPR,
  					   build_pointer_type (type),
*************** initialize_argument_information (num_act
*** 1219,1225 ****
        /* If this is an addressable type, we cannot pre-evaluate it.  Thus,
  	 we cannot consider this function call constant.  */
        if (TREE_ADDRESSABLE (type))
! 	*is_const = 0;
  
        /* Compute the stack-size of this argument.  */
        if (args[i].reg == 0 || args[i].partial != 0
--- 1261,1267 ----
        /* If this is an addressable type, we cannot pre-evaluate it.  Thus,
  	 we cannot consider this function call constant.  */
        if (TREE_ADDRESSABLE (type))
! 	*flags &= ~ECF_CONST;
  
        /* Compute the stack-size of this argument.  */
        if (args[i].reg == 0 || args[i].partial != 0
*************** compute_argument_block_size (reg_parm_st
*** 1359,1365 ****
  
  /* Precompute parameters as needed for a function call.
  
!    IS_CONST indicates the target function is a pure function.
  
     MUST_PREALLOCATE indicates that we must preallocate stack space for
     any stack arguments.
--- 1401,1407 ----
  
  /* Precompute parameters as needed for a function call.
  
!    FLAGS is mask of ECF_* constants.
  
     MUST_PREALLOCATE indicates that we must preallocate stack space for
     any stack arguments.
*************** compute_argument_block_size (reg_parm_st
*** 1372,1379 ****
     ARGS_SIZE contains information about the size of the arg list.  */
  
  static void
! precompute_arguments (is_const, must_preallocate, num_actuals, args, args_size)
!      int is_const;
       int must_preallocate;
       int num_actuals;
       struct arg_data *args;
--- 1414,1421 ----
     ARGS_SIZE contains information about the size of the arg list.  */
  
  static void
! precompute_arguments (flags, must_preallocate, num_actuals, args, args_size)
!      int flags;
       int must_preallocate;
       int num_actuals;
       struct arg_data *args;
*************** precompute_arguments (is_const, must_pre
*** 1395,1401 ****
       which have already been stored into the stack.  */
  
    for (i = 0; i < num_actuals; i++)
!     if (is_const
  	|| ((args_size->var != 0 || args_size->constant != 0)
  	    && calls_function (args[i].tree_value, 1))
  	|| (must_preallocate
--- 1437,1443 ----
       which have already been stored into the stack.  */
  
    for (i = 0; i < num_actuals; i++)
!     if ((flags & ECF_CONST)
  	|| ((args_size->var != 0 || args_size->constant != 0)
  	    && calls_function (args[i].tree_value, 1))
  	|| (must_preallocate
*************** load_register_parameters (args, num_actu
*** 1695,1700 ****
--- 1737,1858 ----
      }
  }
  
+ /* Try to integreate function.  See expand_inline_function for documentation
+    about the parameters.  */
+ 
+ static rtx
+ try_to_integrate (fndecl, actparms, target, ignore, exp, structure_value_addr)
+      tree fndecl;
+      tree actparms;
+      rtx target;
+      int ignore;
+      tree exp;
+      rtx structure_value_addr;
+ {
+   rtx temp;
+   rtx before_call;
+   int i;
+   rtx old_stack_level = 0;
+   int reg_parm_stack_space;
+ 
+ #ifdef REG_PARM_STACK_SPACE
+ #ifdef MAYBE_REG_PARM_STACK_SPACE
+   reg_parm_stack_space = MAYBE_REG_PARM_STACK_SPACE;
+ #else
+   reg_parm_stack_space = REG_PARM_STACK_SPACE (fndecl);
+ #endif
+ #endif
+ 
+   before_call = get_last_insn ();
+ 
+   temp = expand_inline_function (fndecl, actparms, target,
+ 				 ignore, TREE_TYPE (exp),
+ 				 structure_value_addr);
+ 
+   /* If inlining succeeded, return.  */
+   if (temp != (rtx) (HOST_WIDE_INT) - 1)
+     {
+       if (ACCUMULATE_OUTGOING_ARGS)
+ 	{
+ 	  /* If the outgoing argument list must be preserved, push
+ 	     the stack before executing the inlined function if it
+ 	     makes any calls.  */
+ 
+ 	  for (i = reg_parm_stack_space - 1; i >= 0; i--)
+ 	    if (i < highest_outgoing_arg_in_use && stack_usage_map[i] != 0)
+ 	      break;
+ 
+ 	  if (stack_arg_under_construction || i >= 0)
+ 	    {
+ 	      rtx first_insn
+ 		= before_call ? NEXT_INSN (before_call) : get_insns ();
+ 	      rtx insn = NULL_RTX, seq;
+ 
+ 	      /* Look for a call in the inline function code.
+ 	         If DECL_SAVED_INSNS (fndecl)->outgoing_args_size is
+ 	         nonzero then there is a call and it is not necessary
+ 	         to scan the insns.  */
+ 
+ 	      if (DECL_SAVED_INSNS (fndecl)->outgoing_args_size == 0)
+ 		for (insn = first_insn; insn; insn = NEXT_INSN (insn))
+ 		  if (GET_CODE (insn) == CALL_INSN)
+ 		    break;
+ 
+ 	      if (insn)
+ 		{
+ 		  /* Reserve enough stack space so that the largest
+ 		     argument list of any function call in the inline
+ 		     function does not overlap the argument list being
+ 		     evaluated.  This is usually an overestimate because
+ 		     allocate_dynamic_stack_space reserves space for an
+ 		     outgoing argument list in addition to the requested
+ 		     space, but there is no way to ask for stack space such
+ 		     that an argument list of a certain length can be
+ 		     safely constructed. 
+ 
+ 		     Add the stack space reserved for register arguments, if
+ 		     any, in the inline function.  What is really needed is the
+ 		     largest value of reg_parm_stack_space in the inline
+ 		     function, but that is not available.  Using the current
+ 		     value of reg_parm_stack_space is wrong, but gives
+ 		     correct results on all supported machines.  */
+ 
+ 		  int adjust = (DECL_SAVED_INSNS (fndecl)->outgoing_args_size
+ 				+ reg_parm_stack_space);
+ 
+ 		  start_sequence ();
+ 		  emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX);
+ 		  allocate_dynamic_stack_space (GEN_INT (adjust),
+ 						NULL_RTX, BITS_PER_UNIT);
+ 		  seq = get_insns ();
+ 		  end_sequence ();
+ 		  emit_insns_before (seq, first_insn);
+ 		  emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
+ 		}
+ 	    }
+ 	}
+ 
+       /* If the result is equivalent to TARGET, return TARGET to simplify
+          checks in store_expr.  They can be equivalent but not equal in the
+          case of a function that returns BLKmode.  */
+       if (temp != target && rtx_equal_p (temp, target))
+ 	return target;
+       return temp;
+     }
+ 
+   /* If inlining failed, mark FNDECL as needing to be compiled
+      separately after all.  If function was declared inline,
+      give a warning.  */
+   if (DECL_INLINE (fndecl) && warn_inline && !flag_no_inline
+       && optimize > 0 && !TREE_ADDRESSABLE (fndecl))
+     {
+       warning_with_decl (fndecl, "inlining failed in call to `%s'");
+       warning ("called from here");
+     }
+   mark_addressable (fndecl);
+   return NULL_RTX;
+ }
+ 
  /* Generate all the code for a function call
     and return an rtx for its value.
     Store the value in TARGET (specified as an rtx) if convenient.
*************** expand_call (exp, target, ignore)
*** 1726,1732 ****
       or 0 if the function is computed (not known by name).  */
    tree fndecl = 0;
    char *name = 0;
-   rtx before_call;
    rtx insn;
    int try_tail_call;
    int pass;
--- 1884,1889 ----
*************** expand_call (exp, target, ignore)
*** 1785,1810 ****
       (on machines that lack push insns), or 0 if space not preallocated.  */
    rtx argblock = 0;
  
!   /* Nonzero if it is plausible that this is a call to alloca.  */
!   int may_be_alloca;
!   /* Nonzero if this is a call to malloc or a related function. */
!   int is_malloc;
!   /* Nonzero if this is a call to setjmp or a related function.  */
!   int returns_twice;
!   /* Nonzero if this is a call to `longjmp'.  */
!   int is_longjmp;
!   /* Nonzero if this is a syscall that makes a new process in the image of
!      the current one.  */
!   int fork_or_exec;
    /* Nonzero if this is a call to an inline function.  */
    int is_integrable = 0;
-   /* Nonzero if this is a call to a `const' function.
-      Note that only explicitly named functions are handled as `const' here.  */
-   int is_const = 0;
-   /* Nonzero if this is a call to a `volatile' function.  */
-   int is_volatile = 0;
-   /* Nonzero if this is a call to a function that won't throw an exception.  */
-   int nothrow = TREE_NOTHROW (exp);
  #ifdef REG_PARM_STACK_SPACE
    /* Define the boundary of the register parm stack space that needs to be
       save, if any.  */
--- 1942,1951 ----
       (on machines that lack push insns), or 0 if space not preallocated.  */
    rtx argblock = 0;
  
!   /* Mask of ECF_ flags.  */
!   int flags = 0;
    /* Nonzero if this is a call to an inline function.  */
    int is_integrable = 0;
  #ifdef REG_PARM_STACK_SPACE
    /* Define the boundary of the register parm stack space that needs to be
       save, if any.  */
*************** expand_call (exp, target, ignore)
*** 1831,1836 ****
--- 1972,1981 ----
    if (current_function_check_memory_usage)
      target = 0;
  
+   /* See if this is "nothrow" function call.  */
+   if (TREE_NOTHROW (exp))
+     flags |= ECF_NOTHROW;
+ 
    /* See if we can find a DECL-node for the actual function.
       As a result, decide whether this is a call to an integrable function.  */
  
*************** expand_call (exp, target, ignore)
*** 1864,1887 ****
  	      mark_addressable (fndecl);
  	    }
  
! 	  if (TREE_READONLY (fndecl) && ! TREE_THIS_VOLATILE (fndecl)
! 	      && TYPE_MODE (TREE_TYPE (exp)) != VOIDmode)
! 	    is_const = 1;
! 
! 	  if (TREE_THIS_VOLATILE (fndecl))
! 	    is_volatile = 1;
! 
! 	  if (TREE_NOTHROW (fndecl))
! 	    nothrow = 1;
  	}
      }
  
    /* If we don't have specific function to call, see if we have a 
!      constant or `noreturn' function from the type.  */
    if (fndecl == 0)
      {
!       is_const = TREE_READONLY (TREE_TYPE (TREE_TYPE (p)));
!       is_volatile = TREE_THIS_VOLATILE (TREE_TYPE (TREE_TYPE (p)));
      }
  
  #ifdef REG_PARM_STACK_SPACE
--- 2009,2023 ----
  	      mark_addressable (fndecl);
  	    }
  
! 	  flags |= flags_from_decl_or_type (fndecl);
  	}
      }
  
    /* If we don't have specific function to call, see if we have a 
!      attributes set in the type.  */
    if (fndecl == 0)
      {
!       flags |= flags_from_decl_or_type (TREE_TYPE (TREE_TYPE (p)));
      }
  
  #ifdef REG_PARM_STACK_SPACE
*************** expand_call (exp, target, ignore)
*** 1908,1914 ****
    if (aggregate_value_p (exp))
      {
        /* This call returns a big structure.  */
!       is_const = 0;
  
  #ifdef PCC_STATIC_STRUCT_RETURN
        {
--- 2044,2050 ----
    if (aggregate_value_p (exp))
      {
        /* This call returns a big structure.  */
!       flags &= ~ECF_CONST;
  
  #ifdef PCC_STATIC_STRUCT_RETURN
        {
*************** expand_call (exp, target, ignore)
*** 1959,2053 ****
  
    if (is_integrable)
      {
!       rtx temp;
! 
!       before_call = get_last_insn ();
! 
!       temp = expand_inline_function (fndecl, actparms, target,
! 				     ignore, TREE_TYPE (exp),
! 				     structure_value_addr);
! 
!       /* If inlining succeeded, return.  */
!       if (temp != (rtx) (HOST_WIDE_INT) -1)
! 	{
! 	  if (ACCUMULATE_OUTGOING_ARGS)
! 	    {
! 	      /* If the outgoing argument list must be preserved, push
! 		 the stack before executing the inlined function if it
! 		 makes any calls.  */
! 
! 	      for (i = reg_parm_stack_space - 1; i >= 0; i--)
! 		if (i < highest_outgoing_arg_in_use && stack_usage_map[i] != 0)
! 		  break;
! 
! 	      if (stack_arg_under_construction || i >= 0)
! 		{
! 		  rtx first_insn
! 		    = before_call ? NEXT_INSN (before_call) : get_insns ();
! 		  rtx insn = NULL_RTX, seq;
! 
! 		  /* Look for a call in the inline function code.
! 		     If DECL_SAVED_INSNS (fndecl)->outgoing_args_size is
! 		     nonzero then there is a call and it is not necessary
! 		     to scan the insns.  */
! 
! 		  if (DECL_SAVED_INSNS (fndecl)->outgoing_args_size == 0)
! 		    for (insn = first_insn; insn; insn = NEXT_INSN (insn))
! 		      if (GET_CODE (insn) == CALL_INSN)
! 			break;
! 
! 		  if (insn)
! 		    {
! 		      /* Reserve enough stack space so that the largest
! 			 argument list of any function call in the inline
! 			 function does not overlap the argument list being
! 			 evaluated.  This is usually an overestimate because
! 			 allocate_dynamic_stack_space reserves space for an
! 			 outgoing argument list in addition to the requested
! 			 space, but there is no way to ask for stack space such
! 			 that an argument list of a certain length can be
! 			 safely constructed. 
! 
! 			 Add the stack space reserved for register arguments, if
! 			 any, in the inline function.  What is really needed is the
! 			 largest value of reg_parm_stack_space in the inline
! 			 function, but that is not available.  Using the current
! 			 value of reg_parm_stack_space is wrong, but gives
! 			 correct results on all supported machines.  */
! 
! 		      int adjust = (DECL_SAVED_INSNS (fndecl)->outgoing_args_size
! 				    + reg_parm_stack_space);
! 
! 		      start_sequence ();
! 		      emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX);
! 		      allocate_dynamic_stack_space (GEN_INT (adjust),
! 						    NULL_RTX, BITS_PER_UNIT);
! 		      seq = get_insns ();
! 		      end_sequence ();
! 		      emit_insns_before (seq, first_insn);
! 		      emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
! 		    }
! 		}
! 	    }
! 
! 	  /* If the result is equivalent to TARGET, return TARGET to simplify
! 	     checks in store_expr.  They can be equivalent but not equal in the
! 	     case of a function that returns BLKmode.  */
! 	  if (temp != target && rtx_equal_p (temp, target))
! 	    return target;
! 	  return temp;
! 	}
! 
!       /* If inlining failed, mark FNDECL as needing to be compiled
! 	 separately after all.  If function was declared inline,
! 	 give a warning.  */
!       if (DECL_INLINE (fndecl) && warn_inline && !flag_no_inline
! 	  && optimize > 0 && ! TREE_ADDRESSABLE (fndecl))
! 	{
! 	  warning_with_decl (fndecl, "inlining failed in call to `%s'");
! 	  warning ("called from here");
! 	}
!       mark_addressable (fndecl);
      }
  
    currently_expanding_call++;
--- 2095,2105 ----
  
    if (is_integrable)
      {
!       rtx temp = try_to_integrate (fndecl, actparms, target,
! 				   ignore, TREE_TYPE (exp),
! 				   structure_value_addr);
!       if (temp)
! 	return temp;
      }
  
    currently_expanding_call++;
*************** expand_call (exp, target, ignore)
*** 2163,2172 ****
  
    /* See if this is a call to a function that can return more than once
       or a call to longjmp or malloc.  */
!   special_function_p (fndecl, &returns_twice, &is_longjmp, &fork_or_exec,
! 		      &is_malloc, &may_be_alloca);
  
!   if (may_be_alloca)
      current_function_calls_alloca = 1;
  
    /* Operand 0 is a pointer-to-function; get the type of the function.  */
--- 2215,2223 ----
  
    /* See if this is a call to a function that can return more than once
       or a call to longjmp or malloc.  */
!   flags |= special_function_p (fndecl, flags);
  
!   if (flags & ECF_MAY_BE_ALLOCA)
      current_function_calls_alloca = 1;
  
    /* Operand 0 is a pointer-to-function; get the type of the function.  */
*************** expand_call (exp, target, ignore)
*** 2226,2232 ****
  	}
  
        /* Other state variables that we must reinitialize each time
! 	 through the loop (that are not initialized by the loop itself.  */
        argblock = 0;
        call_fusage = 0;
  
--- 2277,2283 ----
  	}
  
        /* Other state variables that we must reinitialize each time
! 	 through the loop (that are not initialized by the loop itself).  */
        argblock = 0;
        call_fusage = 0;
  
*************** expand_call (exp, target, ignore)
*** 2238,2244 ****
  
        /* When calling a const function, we must pop the stack args right away,
  	 so that the pop is deleted or moved with the call.  */
!       if (is_const)
  	NO_DEFER_POP;
  
        /* Don't let pending stack adjusts add up to too much.
--- 2289,2295 ----
  
        /* When calling a const function, we must pop the stack args right away,
  	 so that the pop is deleted or moved with the call.  */
!       if (flags & ECF_CONST)
  	NO_DEFER_POP;
  
        /* Don't let pending stack adjusts add up to too much.
*************** expand_call (exp, target, ignore)
*** 2246,2256 ****
  	 this might be a call to alloca or if we are expanding a sibling
  	 call sequence.  */
        if (pending_stack_adjust >= 32
! 	  || (pending_stack_adjust > 0 && may_be_alloca)
  	  || pass == 0)
  	do_pending_stack_adjust ();
  
!       if (profile_arc_flag && fork_or_exec)
  	{
  	  /* A fork duplicates the profile information, and an exec discards
  	     it.  We can't rely on fork/exec to be paired.  So write out the
--- 2297,2307 ----
  	 this might be a call to alloca or if we are expanding a sibling
  	 call sequence.  */
        if (pending_stack_adjust >= 32
! 	  || (pending_stack_adjust > 0 && (flags & ECF_MAY_BE_ALLOCA))
  	  || pass == 0)
  	do_pending_stack_adjust ();
  
!       if (profile_arc_flag && (flags & ECF_FORK_OR_EXEC))
  	{
  	  /* A fork duplicates the profile information, and an exec discards
  	     it.  We can't rely on fork/exec to be paired.  So write out the
*************** expand_call (exp, target, ignore)
*** 2343,2349 ****
  				       n_named_args, actparms, fndecl,
  				       &args_so_far, reg_parm_stack_space,
  				       &old_stack_level, &old_pending_adj,
! 				       &must_preallocate, &is_const,
  				       (pass == 0) ? ECF_SIBCALL : 0);
  
  #ifdef FINAL_REG_PARM_STACK_SPACE
--- 2394,2400 ----
  				       n_named_args, actparms, fndecl,
  				       &args_so_far, reg_parm_stack_space,
  				       &old_stack_level, &old_pending_adj,
! 				       &must_preallocate, &flags,
  				       (pass == 0) ? ECF_SIBCALL : 0);
  
  #ifdef FINAL_REG_PARM_STACK_SPACE
*************** expand_call (exp, target, ignore)
*** 2360,2366 ****
  
  	     Also do not make a sibling call.  */
  
! 	  is_const = 0;
  	  must_preallocate = 1;
  	  sibcall_failure = 1;
  	}
--- 2411,2417 ----
  
  	     Also do not make a sibling call.  */
  
! 	  flags &= ~ECF_CONST;
  	  must_preallocate = 1;
  	  sibcall_failure = 1;
  	}
*************** expand_call (exp, target, ignore)
*** 2409,2420 ****
  	structure_value_addr = copy_to_reg (structure_value_addr);
  
        /* Precompute any arguments as needed.  */
!       precompute_arguments (is_const, must_preallocate, num_actuals,
  			    args, &args_size);
  
        /* Now we are about to start emitting insns that can be deleted
  	 if a libcall is deleted.  */
!       if (is_const || is_malloc)
  	start_sequence ();
  
        /* If we have no actual push instructions, or shouldn't use them,
--- 2460,2471 ----
  	structure_value_addr = copy_to_reg (structure_value_addr);
  
        /* Precompute any arguments as needed.  */
!       precompute_arguments (flags, must_preallocate, num_actuals,
  			    args, &args_size);
  
        /* Now we are about to start emitting insns that can be deleted
  	 if a libcall is deleted.  */
!       if (flags & (ECF_CONST || ECF_MALLOC))
  	start_sequence ();
  
        /* If we have no actual push instructions, or shouldn't use them,
*************** expand_call (exp, target, ignore)
*** 2595,2601 ****
  	{
  	  /* When the stack adjustment is pending, we get better code
  	     by combining the adjustments.  */
! 	  if (pending_stack_adjust && ! is_const
  	      && ! inhibit_defer_pop)
  	    {
  	      args_size.constant = (unadjusted_args_size
--- 2646,2652 ----
  	{
  	  /* When the stack adjustment is pending, we get better code
  	     by combining the adjustments.  */
! 	  if (pending_stack_adjust && ! (flags & ECF_CONST)
  	      && ! inhibit_defer_pop)
  	    {
  	      args_size.constant = (unadjusted_args_size
*************** expand_call (exp, target, ignore)
*** 2659,2665 ****
  
        for (i = 0; i < num_actuals; i++)
  	if (args[i].reg == 0 || args[i].pass_on_stack)
! 	  store_one_arg (&args[i], argblock, may_be_alloca,
  			 args_size.var != 0, reg_parm_stack_space);
  
        /* If we have a parm that is passed in registers but not in memory
--- 2710,2716 ----
  
        for (i = 0; i < num_actuals; i++)
  	if (args[i].reg == 0 || args[i].pass_on_stack)
! 	  store_one_arg (&args[i], argblock, flags & ECF_MAY_BE_ALLOCA,
  			 args_size.var != 0, reg_parm_stack_space);
  
        /* If we have a parm that is passed in registers but not in memory
*************** expand_call (exp, target, ignore)
*** 2674,2680 ****
        if (reg_parm_seen)
  	for (i = 0; i < num_actuals; i++)
  	  if (args[i].partial != 0 && ! args[i].pass_on_stack)
! 	    store_one_arg (&args[i], argblock, may_be_alloca,
  			   args_size.var != 0, reg_parm_stack_space);
  
  #ifdef PREFERRED_STACK_BOUNDARY
--- 2725,2731 ----
        if (reg_parm_seen)
  	for (i = 0; i < num_actuals; i++)
  	  if (args[i].partial != 0 && ! args[i].pass_on_stack)
! 	    store_one_arg (&args[i], argblock, flags & ECF_MAY_BE_ALLOCA,
  			   args_size.var != 0, reg_parm_stack_space);
  
  #ifdef PREFERRED_STACK_BOUNDARY
*************** expand_call (exp, target, ignore)
*** 2748,2762 ****
        emit_call_1 (funexp, fndecl, funtype, unadjusted_args_size,
  		   args_size.constant, struct_value_size,
  		   next_arg_reg, valreg, old_inhibit_defer_pop, call_fusage,
! 		   ((is_const ? ECF_IS_CONST : 0)
! 		    | (nothrow ? ECF_NOTHROW : 0)
! 		    | (pass == 0 ? ECF_SIBCALL : 0)));
  
        /* If call is cse'able, make appropriate pair of reg-notes around it.
  	 Test valreg so we don't crash; may safely ignore `const'
  	 if return type is void.  Disable for PARALLEL return values, because
  	 we have no way to move such values into a pseudo register.  */
!       if (is_const && valreg != 0 && GET_CODE (valreg) != PARALLEL)
  	{
  	  rtx note = 0;
  	  rtx temp = gen_reg_rtx (GET_MODE (valreg));
--- 2799,2811 ----
        emit_call_1 (funexp, fndecl, funtype, unadjusted_args_size,
  		   args_size.constant, struct_value_size,
  		   next_arg_reg, valreg, old_inhibit_defer_pop, call_fusage,
! 		   flags | (pass == 0 ? ECF_SIBCALL : 0));
  
        /* If call is cse'able, make appropriate pair of reg-notes around it.
  	 Test valreg so we don't crash; may safely ignore `const'
  	 if return type is void.  Disable for PARALLEL return values, because
  	 we have no way to move such values into a pseudo register.  */
!       if ((flags & ECF_CONST) && valreg != 0 && GET_CODE (valreg) != PARALLEL)
  	{
  	  rtx note = 0;
  	  rtx temp = gen_reg_rtx (GET_MODE (valreg));
*************** expand_call (exp, target, ignore)
*** 2786,2792 ****
    
  	  valreg = temp;
  	}
!       else if (is_const)
  	{
  	  /* Otherwise, just write out the sequence without a note.  */
  	  rtx insns = get_insns ();
--- 2835,2841 ----
    
  	  valreg = temp;
  	}
!       else if (flags & ECF_CONST)
  	{
  	  /* Otherwise, just write out the sequence without a note.  */
  	  rtx insns = get_insns ();
*************** expand_call (exp, target, ignore)
*** 2794,2800 ****
  	  end_sequence ();
  	  emit_insns (insns);
  	}
!       else if (is_malloc)
  	{
  	  rtx temp = gen_reg_rtx (GET_MODE (valreg));
  	  rtx last, insns;
--- 2843,2849 ----
  	  end_sequence ();
  	  emit_insns (insns);
  	}
!       else if (flags & ECF_MALLOC)
  	{
  	  rtx temp = gen_reg_rtx (GET_MODE (valreg));
  	  rtx last, insns;
*************** expand_call (exp, target, ignore)
*** 2822,2828 ****
  	 if nonvolatile values are live.  For functions that cannot return,
  	 inform flow that control does not fall through.  */
  
!       if (returns_twice || is_volatile || is_longjmp || pass == 0)
  	{
  	  /* The barrier or NOTE_INSN_SETJMP note must be emitted
  	     immediately after the CALL_INSN.  Some ports emit more
--- 2871,2877 ----
  	 if nonvolatile values are live.  For functions that cannot return,
  	 inform flow that control does not fall through.  */
  
!       if ((flags & (ECF_RETURNS_TWICE | ECF_NORETURN | ECF_LONGJMP)) || pass == 0)
  	{
  	  /* The barrier or NOTE_INSN_SETJMP note must be emitted
  	     immediately after the CALL_INSN.  Some ports emit more
*************** expand_call (exp, target, ignore)
*** 2837,2843 ****
  		abort ();
  	    }
  
! 	  if (returns_twice)
  	    {
  	      emit_note_after (NOTE_INSN_SETJMP, last);
  	      current_function_calls_setjmp = 1;
--- 2886,2892 ----
  		abort ();
  	    }
  
! 	  if (flags & ECF_RETURNS_TWICE)
  	    {
  	      emit_note_after (NOTE_INSN_SETJMP, last);
  	      current_function_calls_setjmp = 1;
*************** expand_call (exp, target, ignore)
*** 2847,2853 ****
  	    emit_barrier_after (last);
  	}
  
!       if (is_longjmp)
  	current_function_calls_longjmp = 1, sibcall_failure = 1;
  
        /* If this function is returning into a memory location marked as
--- 2896,2902 ----
  	    emit_barrier_after (last);
  	}
  
!       if (flags & ECF_LONGJMP)
  	current_function_calls_longjmp = 1, sibcall_failure = 1;
  
        /* If this function is returning into a memory location marked as
*************** expand_call (exp, target, ignore)
*** 3004,3010 ****
  	 Check for the handler slots since we might not have a save area
  	 for non-local gotos.  */
  
!       if (may_be_alloca && nonlocal_goto_handler_slots != 0)
  	emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level, NULL_RTX);
  
        pop_temp_slots ();
--- 3053,3059 ----
  	 Check for the handler slots since we might not have a save area
  	 for non-local gotos.  */
  
!       if ((flags & ECF_MAY_BE_ALLOCA) && nonlocal_goto_handler_slots != 0)
  	emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level, NULL_RTX);
  
        pop_temp_slots ();
*************** emit_library_call_value_1 (retval, orgfu
*** 3139,3147 ****
    rtx mem_value = 0;
    int pcc_struct_value = 0;
    int struct_value_size = 0;
!   int is_const;
    int reg_parm_stack_space = 0;
-   int nothrow;
    int needed;
  
  #ifdef REG_PARM_STACK_SPACE
--- 3188,3195 ----
    rtx mem_value = 0;
    int pcc_struct_value = 0;
    int struct_value_size = 0;
!   int flags = 0;
    int reg_parm_stack_space = 0;
    int needed;
  
  #ifdef REG_PARM_STACK_SPACE
*************** emit_library_call_value_1 (retval, orgfu
*** 3163,3172 ****
  #endif
  #endif
  
!   is_const = no_queue;
    fun = orgfun;
  
!   nothrow = libfunc_nothrow (fun);
  
  #ifdef PREFERRED_STACK_BOUNDARY
    /* Ensure current function's preferred stack boundary is at least
--- 3211,3222 ----
  #endif
  #endif
  
!   if (no_queue)
!     flags |= ECF_CONST;
    fun = orgfun;
  
!   if (libfunc_nothrow (fun))
!     flags |= ECF_NOTHROW;
  
  #ifdef PREFERRED_STACK_BOUNDARY
    /* Ensure current function's preferred stack boundary is at least
*************** emit_library_call_value_1 (retval, orgfu
*** 3196,3202 ****
  #endif
  
        /* This call returns a big structure.  */
!       is_const = 0;
      }
  
    /* ??? Unfinished: must pass the memory address as an argument.  */
--- 3246,3252 ----
  #endif
  
        /* This call returns a big structure.  */
!       flags &= ~ECF_CONST;
      }
  
    /* ??? Unfinished: must pass the memory address as an argument.  */
*************** emit_library_call_value_1 (retval, orgfu
*** 3636,3644 ****
  	       struct_value_size,
  	       FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1),
  	       mem_value == 0 && outmode != VOIDmode ? hard_libcall_value (outmode) : NULL_RTX,
! 	       old_inhibit_defer_pop + 1, call_fusage,
! 	       ((is_const ? ECF_IS_CONST : 0)
! 		| (nothrow ? ECF_NOTHROW : 0)));
  
    /* Now restore inhibit_defer_pop to its actual original value.  */
    OK_DEFER_POP;
--- 3686,3692 ----
  	       struct_value_size,
  	       FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1),
  	       mem_value == 0 && outmode != VOIDmode ? hard_libcall_value (outmode) : NULL_RTX,
! 	       old_inhibit_defer_pop + 1, call_fusage, flags);
  
    /* Now restore inhibit_defer_pop to its actual original value.  */
    OK_DEFER_POP;
*************** emit_library_call_value_1 (retval, orgfu
*** 3720,3726 ****
  
     NO_QUEUE will be true if and only if the library call is a `const' call
     which will be enclosed in REG_LIBCALL/REG_RETVAL notes; it is equivalent
!    to the variable is_const in expand_call.
  
     NO_QUEUE must be true for const calls, because if it isn't, then
     any pending increment will be emitted between REG_LIBCALL/REG_RETVAL notes,
--- 3768,3774 ----
  
     NO_QUEUE will be true if and only if the library call is a `const' call
     which will be enclosed in REG_LIBCALL/REG_RETVAL notes; it is equivalent
!    to the flag ECF_CONST in expand_call.
  
     NO_QUEUE must be true for const calls, because if it isn't, then
     any pending increment will be emitted between REG_LIBCALL/REG_RETVAL notes,


More information about the Gcc-patches mailing list