public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Cleanup patch
@ 1999-01-06 15:15 Jeffrey A Law
  1999-01-06 17:24 ` Mark Mitchell
  0 siblings, 1 reply; 4+ messages in thread
From: Jeffrey A Law @ 1999-01-06 15:15 UTC (permalink / raw)
  To: egcs-patches

This patch breaks up parts of expand_call into some smaller, easier to
read functions.  It should not change the behavior of the compiler in
any way shape or form.


        * calls.c (special_function_p): New function broken out of
        expand_call.
        (precompute_register_parameters): Likewise.
        (store_one_arg): Likewise.
        (store_unaligned_argumetns_into_pseudos): Likewise.
        (save_fixed_argument_area): Likewise.
        (restore_fixed_argument_area): Likewise.
        (expand_call): Corresponding changes.

Index: calls.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/calls.c,v
retrieving revision 1.34
diff -c -3 -p -r1.34 calls.c
*** calls.c	1998/12/16 20:54:01	1.34
--- calls.c	1999/01/06 23:10:20
*************** static int highest_outgoing_arg_in_use;
*** 124,136 ****
  int stack_arg_under_construction;
  #endif
  
! static int calls_function	PROTO((tree, int));
! static int calls_function_1	PROTO((tree, int));
! static void emit_call_1		PROTO((rtx, tree, tree, HOST_WIDE_INT,
! 				       HOST_WIDE_INT, rtx, rtx,
! 				       int, rtx, int));
  static void store_one_arg	PROTO ((struct arg_data *, rtx, int, int,
  					int));
  \f
  /* If WHICH is 1, return 1 if EXP contains a call to the built-in function
     `alloca'.
--- 124,147 ----
  int stack_arg_under_construction;
  #endif
  
! static int calls_function	PROTO ((tree, int));
! static int calls_function_1	PROTO ((tree, int));
! static void emit_call_1		PROTO ((rtx, tree, tree, HOST_WIDE_INT,
! 				        HOST_WIDE_INT, rtx, rtx,
! 				        int, rtx, int));
! static void special_function_p	PROTO ((char *, tree, int *, int *,
! 					int *, int *));
! static void precompute_register_parameters	PROTO ((int, struct arg_data *,
! 							int *));
  static void store_one_arg	PROTO ((struct arg_data *, rtx, int, int,
  					int));
+ static void store_unaligned_arguments_into_pseudos PROTO ((struct arg_data *,
+ 							   int));
+ 
+ #if defined(ACCUMULATE_OUTGOING_ARGS) && defined(REG_PARM_STACK_SPACE)
+ static rtx save_fixed_argument_area	PROTO ((int, rtx, int *, int *));
+ static void restore_fixed_argument_area	PROTO ((rtx, rtx, int, int));
+ #endif
  \f
  /* If WHICH is 1, return 1 if EXP contains a call to the built-in function
     `alloca'.
*************** emit_call_1 (funexp, fndecl, funtype, st
*** 475,480 ****
--- 486,823 ----
  #endif
  }
  
+ /* Determine if the function identified by NAME and FNDECL is one with
+    special properties we wish to know about.
+ 
+    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.  */
+ 
+ static void
+ special_function_p (name, fndecl, returns_twice, is_longjmp,
+ 		    is_malloc, may_be_alloca)
+      char *name;
+      tree fndecl;
+      int *returns_twice;
+      int *is_longjmp;
+      int *is_malloc;
+      int *may_be_alloca;
+ {
+   *returns_twice = 0;
+   *is_longjmp = 0;
+   *is_malloc = 0;
+   *may_be_alloca = 0;
+ 
+   /* 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
+     = (name && ((IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 6
+ 		 && name[0] == 'a'
+ 		 && ! strcmp (name, "alloca"))
+ 		|| (IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 16
+ 		    && name[0] == '_'
+ 		    && ! strcmp (name, "__builtin_alloca"))));
+ 
+   if (name != 0 && IDENTIFIER_LENGTH (DECL_NAME (fndecl)) <= 17
+       /* Exclude functions not at the file scope, or not `extern',
+ 	 since they are not the magic functions we would otherwise
+ 	 think they are.  */
+       && DECL_CONTEXT (fndecl) == NULL_TREE && TREE_PUBLIC (fndecl))
+     {
+       char *tname = name;
+ 
+       /* Disregard prefix _, __ or __x.  */
+       if (name[0] == '_')
+ 	{
+ 	  if (name[1] == '_' && name[2] == 'x')
+ 	    tname += 3;
+ 	  else if (name[1] == '_')
+ 	    tname += 2;
+ 	  else
+ 	    tname += 1;
+ 	}
+ 
+       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;
+       /* XXX should have "malloc" attribute on functions instead
+ 	 of recognizing them by name.  */
+       else if (! strcmp (tname, "malloc")
+ 	       || ! strcmp (tname, "calloc")
+ 	       || ! strcmp (tname, "realloc")
+ 	       /* Note use of NAME rather than TNAME here.  These functions
+ 		  are only reserved when preceded with __.  */
+ 	       || ! strcmp (name, "__vn")	/* mangled __builtin_vec_new */
+ 	       || ! strcmp (name, "__nw")	/* mangled __builtin_new */
+ 	       || ! strcmp (name, "__builtin_new")
+ 	       || ! strcmp (name, "__builtin_vec_new"))
+ 	*is_malloc = 1;
+     }
+ }
+ 
+ /* Precompute all register parameters as described by ARGS, storing values
+    into fields within the ARGS array.
+ 
+    NUM_ACTUALS indicates the total number elements in the ARGS array.
+ 
+    Set REG_PARM_SEEN if we encounter a register parameter.  */
+ 
+ static void
+ precompute_register_parameters (num_actuals, args, reg_parm_seen)
+      int num_actuals;
+      struct arg_data *args;
+      int *reg_parm_seen;
+ {
+   int i;
+ 
+   *reg_parm_seen = 0;
+ 
+   for (i = 0; i < num_actuals; i++)
+     if (args[i].reg != 0 && ! args[i].pass_on_stack)
+       {
+ 	*reg_parm_seen = 1;
+ 
+ 	if (args[i].value == 0)
+ 	  {
+ 	    push_temp_slots ();
+ 	    args[i].value = expand_expr (args[i].tree_value, NULL_RTX,
+ 					 VOIDmode, 0);
+ 	    preserve_temp_slots (args[i].value);
+ 	    pop_temp_slots ();
+ 
+ 	    /* ANSI doesn't require a sequence point here,
+ 	       but PCC has one, so this will avoid some problems.  */
+ 	    emit_queue ();
+ 	  }
+ 
+ 	/* If we are to promote the function arg to a wider mode,
+ 	   do it now.  */
+ 
+ 	if (args[i].mode != TYPE_MODE (TREE_TYPE (args[i].tree_value)))
+ 	  args[i].value
+ 	    = convert_modes (args[i].mode,
+ 			     TYPE_MODE (TREE_TYPE (args[i].tree_value)),
+ 			     args[i].value, args[i].unsignedp);
+ 
+ 	/* If the value is expensive, and we are inside an appropriately 
+ 	   short loop, put the value into a pseudo and then put the pseudo
+ 	   into the hard reg.
+ 
+ 	   For small register classes, also do this if this call uses
+ 	   register parameters.  This is to avoid reload conflicts while
+ 	   loading the parameters registers.  */
+ 
+ 	if ((! (GET_CODE (args[i].value) == REG
+ 		|| (GET_CODE (args[i].value) == SUBREG
+ 		    && GET_CODE (SUBREG_REG (args[i].value)) == REG)))
+ 	    && args[i].mode != BLKmode
+ 	    && rtx_cost (args[i].value, SET) > 2
+ 	    && ((SMALL_REGISTER_CLASSES && *reg_parm_seen)
+ 		|| preserve_subexpressions_p ()))
+ 	  args[i].value = copy_to_mode_reg (args[i].mode, args[i].value);
+       }
+ }
+ 
+ #if defined(ACCUMULATE_OUTGOING_ARGS) && defined(REG_PARM_STACK_SPACE)
+ 
+   /* The argument list is the property of the called routine and it
+      may clobber it.  If the fixed area has been used for previous
+      parameters, we must save and restore it.  */
+ static rtx
+ save_fixed_argument_area (reg_parm_stack_space, argblock,
+ 			  low_to_save, high_to_save)
+      int reg_parm_stack_space;
+      rtx argblock;
+      int *low_to_save;
+      int *high_to_save;
+ {
+   int i;
+   rtx save_area = NULL_RTX;
+ 
+   /* Compute the boundary of the that needs to be saved, if any.  */
+ #ifdef ARGS_GROW_DOWNWARD
+   for (i = 0; i < reg_parm_stack_space + 1; i++)
+ #else
+   for (i = 0; i < reg_parm_stack_space; i++)
+ #endif
+     {
+       if (i >= highest_outgoing_arg_in_use
+ 	  || stack_usage_map[i] == 0)
+ 	continue;
+ 
+       if (*low_to_save == -1)
+ 	*low_to_save = i;
+ 
+       *high_to_save = i;
+     }
+ 
+   if (*low_to_save >= 0)
+     {
+       int num_to_save = *high_to_save - *low_to_save + 1;
+       enum machine_mode save_mode
+ 	= mode_for_size (num_to_save * BITS_PER_UNIT, MODE_INT, 1);
+       rtx stack_area;
+ 
+       /* If we don't have the required alignment, must do this in BLKmode.  */
+       if ((*low_to_save & (MIN (GET_MODE_SIZE (save_mode),
+ 			        BIGGEST_ALIGNMENT / UNITS_PER_WORD) - 1)))
+ 	save_mode = BLKmode;
+ 
+ #ifdef ARGS_GROW_DOWNWARD
+       stack_area = gen_rtx_MEM (save_mode,
+ 				memory_address (save_mode,
+ 						plus_constant (argblock,
+ 							       - *high_to_save)));
+ #else
+       stack_area = gen_rtx_MEM (save_mode,
+ 				memory_address (save_mode,
+ 						plus_constant (argblock,
+ 							       *low_to_save)));
+ #endif
+       if (save_mode == BLKmode)
+ 	{
+ 	  save_area = assign_stack_temp (BLKmode, num_to_save, 0);
+ 	  MEM_IN_STRUCT_P (save_area) = 0;
+ 	  emit_block_move (validize_mem (save_area), stack_area,
+ 			   GEN_INT (num_to_save),
+ 			   PARM_BOUNDARY / BITS_PER_UNIT);
+ 	}
+       else
+ 	{
+ 	  save_area = gen_reg_rtx (save_mode);
+ 	  emit_move_insn (save_area, stack_area);
+ 	}
+     }
+   return save_area;
+ }
+ 
+ static void
+ restore_fixed_argument_area (save_area, argblock, high_to_save, low_to_save)
+      rtx save_area;
+      rtx argblock;
+      int high_to_save;
+      int low_to_save;
+ {
+   enum machine_mode save_mode = GET_MODE (save_area);
+ #ifdef ARGS_GROW_DOWNWARD
+   rtx stack_area
+     = gen_rtx_MEM (save_mode,
+ 		   memory_address (save_mode,
+ 				   plus_constant (argblock,
+ 						  - high_to_save)));
+ #else
+   rtx stack_area
+     = gen_rtx_MEM (save_mode,
+ 		   memory_address (save_mode,
+ 				   plus_constant (argblock,
+ 						  low_to_save)));
+ #endif
+ 
+   if (save_mode != BLKmode)
+     emit_move_insn (stack_area, save_area);
+   else
+     emit_block_move (stack_area, validize_mem (save_area),
+ 		     GEN_INT (high_to_save - low_to_save + 1),
+ 		     PARM_BOUNDARY / BITS_PER_UNIT);
+ }
+ #endif
+ 	  
+ /* If any elements in ARGS refer to parameters that are to be passed in
+    registers, but not in memory, and whose alignment does not permit a
+    direct copy into registers.  Copy the values into a group of pseudos
+    which we will later copy into the appropriate hard registers.  */
+ static void
+ store_unaligned_arguments_into_pseudos (args, num_actuals)
+      struct arg_data *args;
+      int num_actuals;
+ {
+   int i, j;
+      
+   for (i = 0; i < num_actuals; i++)
+     if (args[i].reg != 0 && ! args[i].pass_on_stack
+ 	&& args[i].mode == BLKmode
+ 	&& (TYPE_ALIGN (TREE_TYPE (args[i].tree_value))
+ 	    < (unsigned int) MIN (BIGGEST_ALIGNMENT, BITS_PER_WORD)))
+       {
+ 	int bytes = int_size_in_bytes (TREE_TYPE (args[i].tree_value));
+ 	int big_endian_correction = 0;
+ 
+ 	args[i].n_aligned_regs
+ 	  = args[i].partial ? args[i].partial
+ 	    : (bytes + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD;
+ 
+ 	args[i].aligned_regs = (rtx *) alloca (sizeof (rtx)
+ 					       * args[i].n_aligned_regs);
+ 
+ 	/* Structures smaller than a word are aligned to the least
+ 	   significant byte (to the right).  On a BYTES_BIG_ENDIAN machine,
+ 	   this means we must skip the empty high order bytes when
+ 	   calculating the bit offset.  */
+ 	if (BYTES_BIG_ENDIAN && bytes < UNITS_PER_WORD)
+ 	  big_endian_correction = (BITS_PER_WORD  - (bytes * BITS_PER_UNIT));
+ 
+ 	for (j = 0; j < args[i].n_aligned_regs; j++)
+ 	  {
+ 	    rtx reg = gen_reg_rtx (word_mode);
+ 	    rtx word = operand_subword_force (args[i].value, j, BLKmode);
+ 	    int bitsize = MIN (bytes * BITS_PER_UNIT, BITS_PER_WORD);
+ 	    int bitalign = TYPE_ALIGN (TREE_TYPE (args[i].tree_value));
+ 
+ 	    args[i].aligned_regs[j] = reg;
+ 
+ 	    /* There is no need to restrict this code to loading items
+ 	       in TYPE_ALIGN sized hunks.  The bitfield instructions can
+ 	       load up entire word sized registers efficiently.
+ 
+ 	       ??? This may not be needed anymore.
+ 	       We use to emit a clobber here but that doesn't let later
+ 	       passes optimize the instructions we emit.  By storing 0 into
+ 	       the register later passes know the first AND to zero out the
+ 	       bitfield being set in the register is unnecessary.  The store
+ 	       of 0 will be deleted as will at least the first AND.  */
+ 
+ 	    emit_move_insn (reg, const0_rtx);
+ 
+ 	    bytes -= bitsize / BITS_PER_UNIT;
+ 	    store_bit_field (reg, bitsize, big_endian_correction, word_mode,
+ 			     extract_bit_field (word, bitsize, 0, 1,
+ 						NULL_RTX, word_mode,
+ 						word_mode,
+ 						bitalign / BITS_PER_UNIT,
+ 						BITS_PER_WORD),
+ 			     bitalign / BITS_PER_UNIT, BITS_PER_WORD);
+ 	  }
+       }
+ }
+ 
  /* 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)
*** 827,916 ****
    if (fndecl && DECL_NAME (fndecl))
      name = IDENTIFIER_POINTER (DECL_NAME (fndecl));
  
- #if 0
-   /* Unless it's a call to a specific function that isn't alloca,
-      if it has one argument, we must assume it might be alloca.  */
- 
-   may_be_alloca
-     = (!(fndecl != 0 && strcmp (name, "alloca"))
-        && actparms != 0
-        && TREE_CHAIN (actparms) == 0);
- #else
-   /* 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
-     = (name && ((IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 6
- 		 && name[0] == 'a'
- 		 && ! strcmp (name, "alloca"))
- 		|| (IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 16
- 		    && name[0] == '_'
- 		    && ! strcmp (name, "__builtin_alloca"))));
- #endif
- 
    /* See if this is a call to a function that can return more than once
!      or a call to longjmp.  */
! 
!   returns_twice = 0;
!   is_longjmp = 0;
!   is_malloc = 0;
! 
!   if (name != 0 && IDENTIFIER_LENGTH (DECL_NAME (fndecl)) <= 17
!       /* Exclude functions not at the file scope, or not `extern',
! 	 since they are not the magic functions we would otherwise
! 	 think they are.  */
!       && DECL_CONTEXT (fndecl) == NULL_TREE && TREE_PUBLIC (fndecl))
!     {
!       char *tname = name;
  
-       /* Disregard prefix _, __ or __x.  */
-       if (name[0] == '_')
- 	{
- 	  if (name[1] == '_' && name[2] == 'x')
- 	    tname += 3;
- 	  else if (name[1] == '_')
- 	    tname += 2;
- 	  else
- 	    tname += 1;
- 	}
- 
-       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;
-       /* XXX should have "malloc" attribute on functions instead
- 	 of recognizing them by name.  */
-       else if (! strcmp (tname, "malloc")
- 	       || ! strcmp (tname, "calloc")
- 	       || ! strcmp (tname, "realloc")
- 	       /* Note use of NAME rather than TNAME here.  These functions
- 		  are only reserved when preceded with __.  */
- 	       || ! strcmp (name, "__vn")	/* mangled __builtin_vec_new */
- 	       || ! strcmp (name, "__nw")	/* mangled __builtin_new */
- 	       || ! strcmp (name, "__builtin_new")
- 	       || ! strcmp (name, "__builtin_vec_new"))
- 	is_malloc = 1;
-     }
- 
    if (may_be_alloca)
      current_function_calls_alloca = 1;
  
--- 1170,1180 ----
    if (fndecl && DECL_NAME (fndecl))
      name = IDENTIFIER_POINTER (DECL_NAME (fndecl));
  
    /* 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 (name, fndecl, &returns_twice, &is_longjmp,
! 		      &is_malloc, &may_be_alloca);
  
    if (may_be_alloca)
      current_function_calls_alloca = 1;
  
*************** expand_call (exp, target, ignore)
*** 1650,1764 ****
  
    /* Precompute all register parameters.  It isn't safe to compute anything
       once we have started filling any specific hard regs.  */
!   reg_parm_seen = 0;
!   for (i = 0; i < num_actuals; i++)
!     if (args[i].reg != 0 && ! args[i].pass_on_stack)
!       {
! 	reg_parm_seen = 1;
! 
! 	if (args[i].value == 0)
! 	  {
! 	    push_temp_slots ();
! 	    args[i].value = expand_expr (args[i].tree_value, NULL_RTX,
! 					 VOIDmode, 0);
! 	    preserve_temp_slots (args[i].value);
! 	    pop_temp_slots ();
  
- 	    /* ANSI doesn't require a sequence point here,
- 	       but PCC has one, so this will avoid some problems.  */
- 	    emit_queue ();
- 	  }
- 
- 	/* If we are to promote the function arg to a wider mode,
- 	   do it now.  */
- 
- 	if (args[i].mode != TYPE_MODE (TREE_TYPE (args[i].tree_value)))
- 	  args[i].value
- 	    = convert_modes (args[i].mode,
- 			     TYPE_MODE (TREE_TYPE (args[i].tree_value)),
- 			     args[i].value, args[i].unsignedp);
- 
- 	/* If the value is expensive, and we are inside an appropriately 
- 	   short loop, put the value into a pseudo and then put the pseudo
- 	   into the hard reg.
- 
- 	   For small register classes, also do this if this call uses
- 	   register parameters.  This is to avoid reload conflicts while
- 	   loading the parameters registers.  */
- 
- 	if ((! (GET_CODE (args[i].value) == REG
- 		|| (GET_CODE (args[i].value) == SUBREG
- 		    && GET_CODE (SUBREG_REG (args[i].value)) == REG)))
- 	    && args[i].mode != BLKmode
- 	    && rtx_cost (args[i].value, SET) > 2
- 	    && ((SMALL_REGISTER_CLASSES && reg_parm_seen)
- 		|| preserve_subexpressions_p ()))
- 	  args[i].value = copy_to_mode_reg (args[i].mode, args[i].value);
-       }
- 
  #if defined(ACCUMULATE_OUTGOING_ARGS) && defined(REG_PARM_STACK_SPACE)
- 
-   /* The argument list is the property of the called routine and it
-      may clobber it.  If the fixed area has been used for previous
-      parameters, we must save and restore it.
- 
-      Here we compute the boundary of the that needs to be saved, if any.  */
- 
- #ifdef ARGS_GROW_DOWNWARD
-   for (i = 0; i < reg_parm_stack_space + 1; i++)
- #else
-   for (i = 0; i < reg_parm_stack_space; i++)
- #endif
-     {
-       if (i >=  highest_outgoing_arg_in_use
- 	  || stack_usage_map[i] == 0)
- 	continue;
- 
-       if (low_to_save == -1)
- 	low_to_save = i;
- 
-       high_to_save = i;
-     }
- 
-   if (low_to_save >= 0)
-     {
-       int num_to_save = high_to_save - low_to_save + 1;
-       enum machine_mode save_mode
- 	= mode_for_size (num_to_save * BITS_PER_UNIT, MODE_INT, 1);
-       rtx stack_area;
- 
-       /* If we don't have the required alignment, must do this in BLKmode.  */
-       if ((low_to_save & (MIN (GET_MODE_SIZE (save_mode),
- 			       BIGGEST_ALIGNMENT / UNITS_PER_WORD) - 1)))
- 	save_mode = BLKmode;
  
! #ifdef ARGS_GROW_DOWNWARD
!       stack_area = gen_rtx_MEM (save_mode,
! 				memory_address (save_mode,
! 						plus_constant (argblock,
! 							       - high_to_save)));
! #else
!       stack_area = gen_rtx_MEM (save_mode,
! 				memory_address (save_mode,
! 						plus_constant (argblock,
! 							       low_to_save)));
! #endif
!       if (save_mode == BLKmode)
! 	{
! 	  save_area = assign_stack_temp (BLKmode, num_to_save, 0);
! 	  MEM_IN_STRUCT_P (save_area) = 0;
! 	  emit_block_move (validize_mem (save_area), stack_area,
! 			   GEN_INT (num_to_save),
! 			   PARM_BOUNDARY / BITS_PER_UNIT);
! 	}
!       else
! 	{
! 	  save_area = gen_reg_rtx (save_mode);
! 	  emit_move_insn (save_area, stack_area);
! 	}
!     }
  #endif
! 	  
  
    /* Now store (and compute if necessary) all non-register parms.
       These come before register parms, since they can require block-moves,
--- 1914,1929 ----
  
    /* Precompute all register parameters.  It isn't safe to compute anything
       once we have started filling any specific hard regs.  */
!   precompute_register_parameters (num_actuals, args, &reg_parm_seen);
  
  #if defined(ACCUMULATE_OUTGOING_ARGS) && defined(REG_PARM_STACK_SPACE)
  
!   /* Save the fixed argument area if it's part of the caller's frame and
!      is clobbered by argument setup for this call.  */
!   save_area = save_fixed_argument_area (reg_parm_stack_space, argblock,
! 					&low_to_save, &high_to_save);
  #endif
! 			
  
    /* Now store (and compute if necessary) all non-register parms.
       These come before register parms, since they can require block-moves,
*************** expand_call (exp, target, ignore)
*** 1775,1838 ****
       and whose alignment does not permit a direct copy into registers,
       make a group of pseudos that correspond to each register that we
       will later fill.  */
- 
    if (STRICT_ALIGNMENT)
!     for (i = 0; i < num_actuals; i++)
!       if (args[i].reg != 0 && ! args[i].pass_on_stack
! 	&& args[i].mode == BLKmode
! 	  && (TYPE_ALIGN (TREE_TYPE (args[i].tree_value))
! 	      < (unsigned int) MIN (BIGGEST_ALIGNMENT, BITS_PER_WORD)))
! 	{
! 	  int bytes = int_size_in_bytes (TREE_TYPE (args[i].tree_value));
! 	  int big_endian_correction = 0;
! 
! 	  args[i].n_aligned_regs
! 	    = args[i].partial ? args[i].partial
! 	      : (bytes + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD;
! 
! 	  args[i].aligned_regs = (rtx *) alloca (sizeof (rtx)
! 						 * args[i].n_aligned_regs);
! 
! 	  /* Structures smaller than a word are aligned to the least
! 	     significant byte (to the right).  On a BYTES_BIG_ENDIAN machine,
! 	     this means we must skip the empty high order bytes when
! 	     calculating the bit offset.  */
! 	  if (BYTES_BIG_ENDIAN && bytes < UNITS_PER_WORD)
! 	    big_endian_correction = (BITS_PER_WORD  - (bytes * BITS_PER_UNIT));
  
- 	  for (j = 0; j < args[i].n_aligned_regs; j++)
- 	    {
- 	      rtx reg = gen_reg_rtx (word_mode);
- 	      rtx word = operand_subword_force (args[i].value, j, BLKmode);
- 	      int bitsize = MIN (bytes * BITS_PER_UNIT, BITS_PER_WORD);
- 	      int bitalign = TYPE_ALIGN (TREE_TYPE (args[i].tree_value));
- 
- 	      args[i].aligned_regs[j] = reg;
- 
- 	      /* There is no need to restrict this code to loading items
- 		 in TYPE_ALIGN sized hunks.  The bitfield instructions can
- 		 load up entire word sized registers efficiently.
- 
- 		 ??? This may not be needed anymore.
- 		 We use to emit a clobber here but that doesn't let later
- 		 passes optimize the instructions we emit.  By storing 0 into
- 		 the register later passes know the first AND to zero out the
- 		 bitfield being set in the register is unnecessary.  The store
- 		 of 0 will be deleted as will at least the first AND.  */
- 
- 	      emit_move_insn (reg, const0_rtx);
- 
- 	      bytes -= bitsize / BITS_PER_UNIT;
- 	      store_bit_field (reg, bitsize, big_endian_correction, word_mode,
- 			       extract_bit_field (word, bitsize, 0, 1,
- 						  NULL_RTX, word_mode,
- 						  word_mode,
- 						  bitalign / BITS_PER_UNIT,
- 						  BITS_PER_WORD),
- 			       bitalign / BITS_PER_UNIT, BITS_PER_WORD);
- 	    }
- 	}
- 
    /* Now store any partially-in-registers parm.
       This is the last place a block-move can happen.  */
    if (reg_parm_seen)
--- 1940,1948 ----
       and whose alignment does not permit a direct copy into registers,
       make a group of pseudos that correspond to each register that we
       will later fill.  */
    if (STRICT_ALIGNMENT)
!     store_unaligned_arguments_into_pseudos (args, num_actuals);
  
    /* Now store any partially-in-registers parm.
       This is the last place a block-move can happen.  */
    if (reg_parm_seen)
*************** expand_call (exp, target, ignore)
*** 2152,2182 ****
      {
  #ifdef REG_PARM_STACK_SPACE
        if (save_area)
! 	{
! 	  enum machine_mode save_mode = GET_MODE (save_area);
! #ifdef ARGS_GROW_DOWNWARD
! 	  rtx stack_area
! 	    = gen_rtx_MEM (save_mode,
! 			   memory_address (save_mode,
! 					   plus_constant (argblock,
! 							  - high_to_save)));
! #else
! 	  rtx stack_area
! 	    = gen_rtx_MEM (save_mode,
! 			   memory_address (save_mode,
! 					   plus_constant (argblock,
! 							  low_to_save)));
  #endif
  
- 	  if (save_mode != BLKmode)
- 	    emit_move_insn (stack_area, save_area);
- 	  else
- 	    emit_block_move (stack_area, validize_mem (save_area),
- 			     GEN_INT (high_to_save - low_to_save + 1),
- 			     PARM_BOUNDARY / BITS_PER_UNIT);
- 	}
- #endif
- 	  
        /* If we saved any argument areas, restore them.  */
        for (i = 0; i < num_actuals; i++)
  	if (args[i].save_area)
--- 2262,2271 ----
      {
  #ifdef REG_PARM_STACK_SPACE
        if (save_area)
! 	restore_fixed_argument_area (save_area, argblock,
! 				     high_to_save, low_to_save);
  #endif
  
        /* If we saved any argument areas, restore them.  */
        for (i = 0; i < num_actuals; i++)
  	if (args[i].save_area)


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2011-06-29 20:17 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <4E0A3B51.1050805@free.fr>
     [not found] ` <BANLkTin7PszDoBZ2yshMWuU7Bq_JGT0Xgw@mail.gmail.com>
2011-06-29 20:56   ` cleanup patch François Dumont
1999-01-06 15:15 Cleanup patch Jeffrey A Law
1999-01-06 17:24 ` Mark Mitchell
1999-01-06 17:52   ` Jeffrey A Law

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).