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]

fix execute/20020412-1.c


The problem here is that calling memcpy to place arguments
to a function can clobber arguments already placed.  Fixed
by emitting a loop to do the copy instead of calling the
out-of-line function iff memcpy doesn't take all of its
arguments in registers.

There is still room for improvement, in that in certain
cases we could copy in hunks larger than word-sized.  I
wanted that optimization as a separate patch though.

Tested on i686 and alpha.


r~


        * expr.h (enum block_op_methods): New.
        (emit_block_move): Update prototype.
        * expr.c (block_move_libcall_safe_for_call_parm): New.
        (emit_block_move_via_loop): New.
        (emit_block_move): Use them.  New argument METHOD.
        (emit_push_insn): Always respect the given alignment.
        (expand_assignment): Update call to emit_block_move.
        (store_expr, store_field, expand_expr): Likewise.
        * builtins.c (expand_builtin_apply): Likewise.
        (expand_builtin_memcpy, expand_builtin_va_copy): Likewise.
        * function.c (expand_function_end): Likewise.
        * config/sh/sh.c (sh_initialize_trampoline): Likewise.
        * config/sparc/sparc.c (sparc_va_arg): Likewise.
        * calls.c (expand_call, emit_library_call_value_1): Likewise.
        (save_fixed_argument_area): Use emit_block_move with
        BLOCK_OP_CALL_PARM instead of move_by_pieces.
        (restore_fixed_argument_area): Likewise.
        (store_one_arg): Fix alignment parameter to emit_push_insn.

Index: gcc/builtins.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtins.c,v
retrieving revision 1.159
diff -c -p -d -r1.159 builtins.c
*** gcc/builtins.c	5 Aug 2002 18:46:32 -0000	1.159
--- gcc/builtins.c	29 Aug 2002 19:08:48 -0000
*************** expand_builtin_apply (function, argument
*** 1225,1231 ****
    set_mem_align (dest, PARM_BOUNDARY);
    src = gen_rtx_MEM (BLKmode, incoming_args);
    set_mem_align (src, PARM_BOUNDARY);
!   emit_block_move (dest, src, argsize);
  
    /* Refer to the argument block.  */
    apply_args_size ();
--- 1225,1231 ----
    set_mem_align (dest, PARM_BOUNDARY);
    src = gen_rtx_MEM (BLKmode, incoming_args);
    set_mem_align (src, PARM_BOUNDARY);
!   emit_block_move (dest, src, argsize, BLOCK_OP_NORMAL);
  
    /* Refer to the argument block.  */
    apply_args_size ();
*************** expand_builtin_memcpy (arglist, target, 
*** 2000,2006 ****
        set_mem_align (src_mem, src_align);
  
        /* Copy word part most expediently.  */
!       dest_addr = emit_block_move (dest_mem, src_mem, len_rtx);
  
        if (dest_addr == 0)
  	{
--- 2000,2007 ----
        set_mem_align (src_mem, src_align);
  
        /* Copy word part most expediently.  */
!       dest_addr = emit_block_move (dest_mem, src_mem, len_rtx,
! 				   BLOCK_OP_NORMAL);
  
        if (dest_addr == 0)
  	{
*************** expand_builtin_va_copy (arglist)
*** 3298,3304 ****
        set_mem_align (srcb, TYPE_ALIGN (va_list_type_node));
  
        /* Copy.  */
!       emit_block_move (dstb, srcb, size);
      }
  
    return const0_rtx;
--- 3299,3305 ----
        set_mem_align (srcb, TYPE_ALIGN (va_list_type_node));
  
        /* Copy.  */
!       emit_block_move (dstb, srcb, size, BLOCK_OP_NORMAL);
      }
  
    return const0_rtx;
Index: gcc/calls.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/calls.c,v
retrieving revision 1.231
diff -c -p -d -r1.231 calls.c
*** gcc/calls.c	15 Aug 2002 00:07:54 -0000	1.231
--- gcc/calls.c	29 Aug 2002 19:08:49 -0000
*************** save_fixed_argument_area (reg_parm_stack
*** 967,977 ****
        if (save_mode == BLKmode)
  	{
  	  save_area = assign_stack_temp (BLKmode, num_to_save, 0);
! 	  /* Cannot use emit_block_move here because it can be done by a
! 	     library call which in turn gets into this place again and deadly
! 	     infinite recursion happens.  */
! 	  move_by_pieces (validize_mem (save_area), stack_area, num_to_save,
! 			  PARM_BOUNDARY);
  	}
        else
  	{
--- 967,974 ----
        if (save_mode == BLKmode)
  	{
  	  save_area = assign_stack_temp (BLKmode, num_to_save, 0);
! 	  emit_block_move (validize_mem (save_area), stack_area,
! 			   GEN_INT (num_to_save), BLOCK_OP_CALL_PARM);
  	}
        else
  	{
*************** restore_fixed_argument_area (save_area, 
*** 1008,1018 ****
    if (save_mode != BLKmode)
      emit_move_insn (stack_area, save_area);
    else
!     /* Cannot use emit_block_move here because it can be done by a library
!        call which in turn gets into this place again and deadly infinite
!        recursion happens.  */
!     move_by_pieces (stack_area, validize_mem (save_area),
! 		    high_to_save - low_to_save + 1, PARM_BOUNDARY);
  }
  #endif /* REG_PARM_STACK_SPACE */
  
--- 1005,1013 ----
    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),
! 		     BLOCK_OP_CALL_PARM);
  }
  #endif /* REG_PARM_STACK_SPACE */
  
*************** expand_call (exp, target, ignore)
*** 3317,3325 ****
  		if (save_mode != BLKmode)
  		  emit_move_insn (stack_area, args[i].save_area);
  		else
! 		  emit_block_move (stack_area,
! 				   validize_mem (args[i].save_area),
! 				   GEN_INT (args[i].size.constant));
  	      }
  
  	  highest_outgoing_arg_in_use = initial_highest_arg_in_use;
--- 3312,3320 ----
  		if (save_mode != BLKmode)
  		  emit_move_insn (stack_area, args[i].save_area);
  		else
! 		  emit_block_move (stack_area, args[i].save_area,
! 				   GEN_INT (args[i].size.constant),
! 				   BLOCK_OP_CALL_PARM);
  	      }
  
  	  highest_outgoing_arg_in_use = initial_highest_arg_in_use;
*************** emit_library_call_value_1 (retval, orgfu
*** 3909,3916 ****
  	    {
  	      save_area = assign_stack_temp (BLKmode, num_to_save, 0);
  	      set_mem_align (save_area, PARM_BOUNDARY);
! 	      emit_block_move (validize_mem (save_area), stack_area,
! 			       GEN_INT (num_to_save));
  	    }
  	  else
  	    {
--- 3904,3911 ----
  	    {
  	      save_area = assign_stack_temp (BLKmode, num_to_save, 0);
  	      set_mem_align (save_area, PARM_BOUNDARY);
! 	      emit_block_move (save_area, stack_area, GEN_INT (num_to_save),
! 			       BLOCK_OP_CALL_PARM);
  	    }
  	  else
  	    {
*************** emit_library_call_value_1 (retval, orgfu
*** 3978,3985 ****
  		}
  	    }
  
! 	  emit_push_insn (val, mode, NULL_TREE, NULL_RTX, 0, partial, reg, 0,
! 			  argblock, GEN_INT (argvec[argnum].offset.constant),
  			  reg_parm_stack_space, ARGS_SIZE_RTX (alignment_pad));
  
  	  /* Now mark the segment we just used.  */
--- 3973,3981 ----
  		}
  	    }
  
! 	  emit_push_insn (val, mode, NULL_TREE, NULL_RTX, PARM_BOUNDARY,
! 			  partial, reg, 0, argblock,
! 			  GEN_INT (argvec[argnum].offset.constant),
  			  reg_parm_stack_space, ARGS_SIZE_RTX (alignment_pad));
  
  	  /* Now mark the segment we just used.  */
*************** emit_library_call_value_1 (retval, orgfu
*** 4180,4187 ****
  	  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));
  	}
  #endif
  
--- 4176,4184 ----
  	  if (save_mode != BLKmode)
  	    emit_move_insn (stack_area, save_area);
  	  else
! 	    emit_block_move (stack_area, save_area,
! 			     GEN_INT (high_to_save - low_to_save + 1),
! 			     BLOCK_OP_CALL_PARM);
  	}
  #endif
  
*************** store_one_arg (arg, argblock, flags, var
*** 4358,4364 ****
  		  arg->save_area = assign_temp (nt, 0, 1, 1);
  		  preserve_temp_slots (arg->save_area);
  		  emit_block_move (validize_mem (arg->save_area), stack_area,
! 				   expr_size (arg->tree_value));
  		}
  	      else
  		{
--- 4355,4362 ----
  		  arg->save_area = assign_temp (nt, 0, 1, 1);
  		  preserve_temp_slots (arg->save_area);
  		  emit_block_move (validize_mem (arg->save_area), stack_area,
! 				   expr_size (arg->tree_value),
! 				   BLOCK_OP_CALL_PARM);
  		}
  	      else
  		{
*************** store_one_arg (arg, argblock, flags, var
*** 4479,4486 ****
  
        /* This isn't already where we want it on the stack, so put it there.
  	 This can either be done with push or copy insns.  */
!       emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), NULL_RTX, 0,
! 		      partial, reg, used - size, argblock,
  		      ARGS_SIZE_RTX (arg->offset), reg_parm_stack_space,
  		      ARGS_SIZE_RTX (arg->alignment_pad));
  
--- 4477,4484 ----
  
        /* This isn't already where we want it on the stack, so put it there.
  	 This can either be done with push or copy insns.  */
!       emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), NULL_RTX, 
! 		      PARM_BOUNDARY, partial, reg, used - size, argblock,
  		      ARGS_SIZE_RTX (arg->offset), reg_parm_stack_space,
  		      ARGS_SIZE_RTX (arg->alignment_pad));
  
*************** store_one_arg (arg, argblock, flags, var
*** 4574,4591 ****
            {
  	    rtx size_rtx1 = GEN_INT (reg_parm_stack_space - arg->offset.constant);
  	    emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), size_rtx1,
! 		            TYPE_ALIGN (TREE_TYPE (pval)), partial, reg,
! 			    excess, argblock, ARGS_SIZE_RTX (arg->offset),
! 			    reg_parm_stack_space,
  		            ARGS_SIZE_RTX (arg->alignment_pad));
  	  }
  	}
  	
  
        emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), size_rtx,
! 		      TYPE_ALIGN (TREE_TYPE (pval)), partial, reg, excess,
! 		      argblock, ARGS_SIZE_RTX (arg->offset),
! 		      reg_parm_stack_space,
  		      ARGS_SIZE_RTX (arg->alignment_pad));
  
        /* Unless this is a partially-in-register argument, the argument is now
--- 4572,4589 ----
            {
  	    rtx size_rtx1 = GEN_INT (reg_parm_stack_space - arg->offset.constant);
  	    emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), size_rtx1,
! 		            MAX (PARM_BOUNDARY, TYPE_ALIGN (TREE_TYPE (pval))),
! 			    partial, reg, excess, argblock,
! 			    ARGS_SIZE_RTX (arg->offset), reg_parm_stack_space,
  		            ARGS_SIZE_RTX (arg->alignment_pad));
  	  }
  	}
  	
  
        emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), size_rtx,
! 		      MAX (PARM_BOUNDARY, TYPE_ALIGN (TREE_TYPE (pval))),
! 		      partial, reg, excess, argblock,
! 		      ARGS_SIZE_RTX (arg->offset), reg_parm_stack_space,
  		      ARGS_SIZE_RTX (arg->alignment_pad));
  
        /* Unless this is a partially-in-register argument, the argument is now
Index: gcc/expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.478
diff -c -p -d -r1.478 expr.c
*** gcc/expr.c	20 Aug 2002 09:47:18 -0000	1.478
--- gcc/expr.c	29 Aug 2002 19:08:49 -0000
*************** static unsigned HOST_WIDE_INT move_by_pi
*** 132,140 ****
--- 132,142 ----
  					 unsigned int));
  static void move_by_pieces_1	PARAMS ((rtx (*) (rtx, ...), enum machine_mode,
  					 struct move_by_pieces *));
+ static bool block_move_libcall_safe_for_call_parm PARAMS ((void));
  static bool emit_block_move_via_movstr PARAMS ((rtx, rtx, rtx, unsigned));
  static rtx emit_block_move_via_libcall PARAMS ((rtx, rtx, rtx));
  static tree emit_block_move_libcall_fn PARAMS ((int));
+ static void emit_block_move_via_loop PARAMS ((rtx, rtx, rtx, unsigned));
  static rtx clear_by_pieces_1	PARAMS ((PTR, HOST_WIDE_INT,
  					 enum machine_mode));
  static void clear_by_pieces	PARAMS ((rtx, unsigned HOST_WIDE_INT,
*************** move_by_pieces_1 (genfun, mode, data)
*** 1677,1692 ****
     Both X and Y must be MEM rtx's (perhaps inside VOLATILE) with mode BLKmode.
     SIZE is an rtx that says how long they are.
     ALIGN is the maximum alignment we can assume they have.
  
     Return the address of the new block, if memcpy is called and returns it,
     0 otherwise.  */
  
  rtx
! emit_block_move (x, y, size)
       rtx x, y, size;
  {
    rtx retval = 0;
!   unsigned int align = MIN (MEM_ALIGN (x), MEM_ALIGN (y));
  
    if (GET_MODE (x) != BLKmode)
      abort ();
--- 1679,1721 ----
     Both X and Y must be MEM rtx's (perhaps inside VOLATILE) with mode BLKmode.
     SIZE is an rtx that says how long they are.
     ALIGN is the maximum alignment we can assume they have.
+    METHOD describes what kind of copy this is, and what mechanisms may be used.
  
     Return the address of the new block, if memcpy is called and returns it,
     0 otherwise.  */
  
  rtx
! emit_block_move (x, y, size, method)
       rtx x, y, size;
+      enum block_op_methods method;
  {
+   bool may_use_call;
    rtx retval = 0;
!   unsigned int align;
! 
!   switch (method)
!     {
!     case BLOCK_OP_NORMAL:
!       may_use_call = true;
!       break;
! 
!     case BLOCK_OP_CALL_PARM:
!       may_use_call = block_move_libcall_safe_for_call_parm ();
! 
!       /* Make inhibit_defer_pop nonzero around the library call
! 	 to force it to pop the arguments right away.  */
!       NO_DEFER_POP;
!       break;
! 
!     case BLOCK_OP_NO_LIBCALL:
!       may_use_call = false;
!       break;
! 
!     default:
!       abort ();
!     }
! 
!   align = MIN (MEM_ALIGN (x), MEM_ALIGN (y));
  
    if (GET_MODE (x) != BLKmode)
      abort ();
*************** emit_block_move (x, y, size)
*** 1708,1719 ****
      move_by_pieces (x, y, INTVAL (size), align);
    else if (emit_block_move_via_movstr (x, y, size, align))
      ;
!   else
      retval = emit_block_move_via_libcall (x, y, size);
  
    return retval;
  }
  
  /* A subroutine of emit_block_move.  Expand a movstr pattern; 
     return true if successful.  */
  
--- 1737,1813 ----
      move_by_pieces (x, y, INTVAL (size), align);
    else if (emit_block_move_via_movstr (x, y, size, align))
      ;
!   else if (may_use_call)
      retval = emit_block_move_via_libcall (x, y, size);
+   else
+     emit_block_move_via_loop (x, y, size, align);
+ 
+   if (method == BLOCK_OP_CALL_PARM)
+     OK_DEFER_POP;
  
    return retval;
  }
  
+ /* A subroutine of emit_block_move.  Returns true if calling the 
+    block move libcall will not clobber any parameters which may have
+    already been placed on the stack.  */
+ 
+ static bool
+ block_move_libcall_safe_for_call_parm ()
+ {
+   if (PUSH_ARGS)
+     return true;
+   else
+     {
+       /* Check to see whether memcpy takes all register arguments.  */
+       static enum {
+ 	takes_regs_uninit, takes_regs_no, takes_regs_yes
+       } takes_regs = takes_regs_uninit;
+ 
+       switch (takes_regs)
+ 	{
+ 	case takes_regs_uninit:
+ 	  {
+ 	    CUMULATIVE_ARGS args_so_far;
+ 	    tree fn, arg;
+ 
+ 	    fn = emit_block_move_libcall_fn (false);
+ 	    INIT_CUMULATIVE_ARGS (args_so_far, TREE_TYPE (fn), NULL_RTX, 0);
+ 
+ 	    arg = TYPE_ARG_TYPES (TREE_TYPE (fn));
+ 	    for ( ; arg != void_list_node ; arg = TREE_CHAIN (arg))
+ 	      {
+ 		enum machine_mode mode
+ 		  = TYPE_MODE (TREE_TYPE (TREE_VALUE (arg)));
+ 		rtx tmp = FUNCTION_ARG (args_so_far, mode, NULL_TREE, 1);
+ 		if (!tmp || !REG_P (tmp))
+ 		  goto fail_takes_regs;
+ #ifdef FUNCTION_ARG_PARTIAL_NREGS
+ 		if (FUNCTION_ARG_PARTIAL_NREGS (args_so_far, mode,
+ 						NULL_TREE, 1))
+ 		  goto fail_takes_regs;
+ #endif
+ 		FUNCTION_ARG_ADVANCE (args_so_far, mode, NULL_TREE, 1);
+ 	      }
+ 	  }
+ 	  takes_regs = takes_regs_yes;
+ 	  /* FALLTHRU */
+ 
+ 	case takes_regs_yes:
+ 	  return true;
+ 
+ 	fail_takes_regs:
+ 	  takes_regs = takes_regs_no;
+ 	  /* FALLTHRU */
+ 	case takes_regs_no:
+ 	  return false;
+ 
+ 	default:
+ 	  abort ();
+ 	}
+     }
+ }
+ 
  /* A subroutine of emit_block_move.  Expand a movstr pattern; 
     return true if successful.  */
  
*************** emit_block_move_libcall_fn (for_call)
*** 1919,1924 ****
--- 2013,2071 ----
  
    return fn;
  }
+ 
+ /* A subroutine of emit_block_move.  Copy the data via an explicit
+    loop.  This is used only when libcalls are forbidden.  */
+ /* ??? It'd be nice to copy in hunks larger than QImode.  */
+ 
+ static void
+ emit_block_move_via_loop (x, y, size, align)
+      rtx x, y, size;
+      unsigned int align ATTRIBUTE_UNUSED;
+ {
+   rtx cmp_label, top_label, iter, x_addr, y_addr, tmp;
+   enum machine_mode iter_mode;
+ 
+   iter_mode = GET_MODE (size);
+   if (iter_mode == VOIDmode)
+     iter_mode = word_mode;
+ 
+   top_label = gen_label_rtx ();
+   cmp_label = gen_label_rtx ();
+   iter = gen_reg_rtx (iter_mode);
+ 
+   emit_move_insn (iter, const0_rtx);
+ 
+   x_addr = force_operand (XEXP (x, 0), NULL_RTX);
+   y_addr = force_operand (XEXP (y, 0), NULL_RTX);
+   do_pending_stack_adjust ();
+ 
+   emit_note (NULL, NOTE_INSN_LOOP_BEG);
+ 
+   emit_jump (cmp_label);
+   emit_label (top_label);
+ 
+   tmp = convert_modes (Pmode, iter_mode, iter, true);
+   x_addr = gen_rtx_PLUS (Pmode, x_addr, tmp);
+   y_addr = gen_rtx_PLUS (Pmode, y_addr, tmp);
+   x = change_address (x, QImode, x_addr);
+   y = change_address (y, QImode, y_addr);
+ 
+   emit_move_insn (x, y);
+ 
+   tmp = expand_simple_binop (iter_mode, PLUS, iter, const1_rtx, iter,
+ 			     true, OPTAB_LIB_WIDEN);
+   if (tmp != iter)
+     emit_move_insn (iter, tmp);
+ 
+   emit_note (NULL, NOTE_INSN_LOOP_CONT);
+   emit_label (cmp_label);
+ 
+   emit_cmp_and_jump_insns (iter, size, LT, NULL_RTX, iter_mode,
+ 			   true, top_label);
+ 
+   emit_note (NULL, NOTE_INSN_LOOP_END);
+ }
  
  /* Copy all or part of a value X into registers starting at REGNO.
     The number of registers to be filled is NREGS.  */
*************** emit_push_insn (x, mode, type, size, ali
*** 3623,3638 ****
  		 of sibling calls.  */
  	      set_mem_alias_set (target, 0);
  	    }
- 	  else
- 	    set_mem_align (target, align);
  
! 	  /* Make inhibit_defer_pop nonzero around the library call
! 	     to force it to pop the bcopy-arguments right away.  */
! 	  NO_DEFER_POP;
! 
! 	  emit_block_move (target, xinner, size);
  
! 	  OK_DEFER_POP;
  	}
      }
    else if (partial > 0)
--- 3770,3781 ----
  		 of sibling calls.  */
  	      set_mem_alias_set (target, 0);
  	    }
  
! 	  /* ALIGN may well be better aligned than TYPE, e.g. due to
! 	     PARM_BOUNDARY.  Assume the caller isn't lying.  */
! 	  set_mem_align (target, align);
  
! 	  emit_block_move (target, xinner, size, BLOCK_OP_CALL_PARM);
  	}
      }
    else if (partial > 0)
*************** expand_assignment (to, from, want_value,
*** 3951,3957 ****
        if (GET_CODE (to_rtx) == PARALLEL)
  	emit_group_load (to_rtx, value, int_size_in_bytes (TREE_TYPE (from)));
        else if (GET_MODE (to_rtx) == BLKmode)
! 	emit_block_move (to_rtx, value, expr_size (from));
        else
  	{
  #ifdef POINTERS_EXTEND_UNSIGNED
--- 4094,4100 ----
        if (GET_CODE (to_rtx) == PARALLEL)
  	emit_group_load (to_rtx, value, int_size_in_bytes (TREE_TYPE (from)));
        else if (GET_MODE (to_rtx) == BLKmode)
! 	emit_block_move (to_rtx, value, expr_size (from), BLOCK_OP_NORMAL);
        else
  	{
  #ifdef POINTERS_EXTEND_UNSIGNED
*************** store_expr (exp, target, want_value)
*** 4312,4318 ****
  
  	  if (GET_CODE (size) == CONST_INT
  	      && INTVAL (size) < TREE_STRING_LENGTH (exp))
! 	    emit_block_move (target, temp, size);
  	  else
  	    {
  	      /* Compute the size of the data to copy from the string.  */
--- 4455,4461 ----
  
  	  if (GET_CODE (size) == CONST_INT
  	      && INTVAL (size) < TREE_STRING_LENGTH (exp))
! 	    emit_block_move (target, temp, size, BLOCK_OP_NORMAL);
  	  else
  	    {
  	      /* Compute the size of the data to copy from the string.  */
*************** store_expr (exp, target, want_value)
*** 4326,4332 ****
  
  	      /* Copy that much.  */
  	      copy_size_rtx = convert_to_mode (ptr_mode, copy_size_rtx, 0);
! 	      emit_block_move (target, temp, copy_size_rtx);
  
  	      /* Figure out how much is left in TARGET that we have to clear.
  		 Do all calculations in ptr_mode.  */
--- 4469,4475 ----
  
  	      /* Copy that much.  */
  	      copy_size_rtx = convert_to_mode (ptr_mode, copy_size_rtx, 0);
! 	      emit_block_move (target, temp, copy_size_rtx, BLOCK_OP_NORMAL);
  
  	      /* Figure out how much is left in TARGET that we have to clear.
  		 Do all calculations in ptr_mode.  */
*************** store_expr (exp, target, want_value)
*** 4367,4373 ****
        else if (GET_CODE (target) == PARALLEL)
  	emit_group_load (target, temp, int_size_in_bytes (TREE_TYPE (exp)));
        else if (GET_MODE (temp) == BLKmode)
! 	emit_block_move (target, temp, expr_size (exp));
        else
  	emit_move_insn (target, temp);
      }
--- 4510,4516 ----
        else if (GET_CODE (target) == PARALLEL)
  	emit_group_load (target, temp, int_size_in_bytes (TREE_TYPE (exp)));
        else if (GET_MODE (temp) == BLKmode)
! 	emit_block_move (target, temp, expr_size (exp), BLOCK_OP_NORMAL);
        else
  	emit_move_insn (target, temp);
      }
*************** store_field (target, bitsize, bitpos, mo
*** 5295,5301 ****
  	  target = adjust_address (target, VOIDmode, bitpos / BITS_PER_UNIT);
  	  emit_block_move (target, temp,
  			   GEN_INT ((bitsize + BITS_PER_UNIT - 1)
! 				    / BITS_PER_UNIT));
  
  	  return value_mode == VOIDmode ? const0_rtx : target;
  	}
--- 5438,5445 ----
  	  target = adjust_address (target, VOIDmode, bitpos / BITS_PER_UNIT);
  	  emit_block_move (target, temp,
  			   GEN_INT ((bitsize + BITS_PER_UNIT - 1)
! 				    / BITS_PER_UNIT),
! 			   BLOCK_OP_NORMAL);
  
  	  return value_mode == VOIDmode ? const0_rtx : target;
  	}
*************** expand_expr (exp, target, tmode, modifie
*** 7218,7224 ****
  
  		emit_block_move (target, op0,
  				 GEN_INT ((bitsize + BITS_PER_UNIT - 1)
! 					  / BITS_PER_UNIT));
  
  		return target;
  	      }
--- 7362,7369 ----
  
  		emit_block_move (target, op0,
  				 GEN_INT ((bitsize + BITS_PER_UNIT - 1)
! 					  / BITS_PER_UNIT),
! 				 BLOCK_OP_NORMAL);
  
  		return target;
  	      }
*************** expand_expr (exp, target, tmode, modifie
*** 7634,7640 ****
  
  	      if (GET_MODE (op0) == BLKmode)
  		emit_block_move (new_with_op0_mode, op0,
! 				 GEN_INT (GET_MODE_SIZE (TYPE_MODE (type))));
  	      else
  		emit_move_insn (new_with_op0_mode, op0);
  
--- 7779,7786 ----
  
  	      if (GET_MODE (op0) == BLKmode)
  		emit_block_move (new_with_op0_mode, op0,
! 				 GEN_INT (GET_MODE_SIZE (TYPE_MODE (type))),
! 				 BLOCK_OP_NORMAL);
  	      else
  		emit_move_insn (new_with_op0_mode, op0);
  
*************** expand_expr (exp, target, tmode, modifie
*** 8856,8862 ****
  	      if (TYPE_ALIGN_OK (inner_type))
  		abort ();
  
! 	      emit_block_move (new, op0, expr_size (TREE_OPERAND (exp, 0)));
  	      op0 = new;
  	    }
  
--- 9002,9009 ----
  	      if (TYPE_ALIGN_OK (inner_type))
  		abort ();
  
! 	      emit_block_move (new, op0, expr_size (TREE_OPERAND (exp, 0)),
! 			       BLOCK_OP_NORMAL);
  	      op0 = new;
  	    }
  
Index: gcc/expr.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.h,v
retrieving revision 1.120
diff -c -p -d -r1.120 expr.h
*** gcc/expr.h	3 Aug 2002 20:20:35 -0000	1.120
--- gcc/expr.h	29 Aug 2002 19:08:49 -0000
*************** extern rtx convert_modes PARAMS ((enum m
*** 394,400 ****
  				  rtx, int));
  
  /* Emit code to move a block Y to a block X.  */
! extern rtx emit_block_move PARAMS ((rtx, rtx, rtx));
  
  /* Copy all or part of a value X into registers starting at REGNO.
     The number of registers to be filled is NREGS.  */
--- 394,408 ----
  				  rtx, int));
  
  /* Emit code to move a block Y to a block X.  */
! 
! enum block_op_methods
! {
!   BLOCK_OP_NORMAL,
!   BLOCK_OP_CALL_PARM,
!   BLOCK_OP_NO_LIBCALL
! };
! 
! extern rtx emit_block_move PARAMS ((rtx, rtx, rtx, enum block_op_methods));
  
  /* Copy all or part of a value X into registers starting at REGNO.
     The number of registers to be filled is NREGS.  */
Index: gcc/function.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/function.c,v
retrieving revision 1.380
diff -c -p -d -r1.380 function.c
*** gcc/function.c	6 Aug 2002 20:39:40 -0000	1.380
--- gcc/function.c	29 Aug 2002 19:08:49 -0000
*************** expand_function_end (filename, line, end
*** 6807,6813 ****
  #ifdef TRAMPOLINE_TEMPLATE
        blktramp = replace_equiv_address (initial_trampoline, tramp);
        emit_block_move (blktramp, initial_trampoline,
! 		       GEN_INT (TRAMPOLINE_SIZE));
  #endif
        INITIALIZE_TRAMPOLINE (tramp, XEXP (DECL_RTL (function), 0), context);
        seq = get_insns ();
--- 6807,6813 ----
  #ifdef TRAMPOLINE_TEMPLATE
        blktramp = replace_equiv_address (initial_trampoline, tramp);
        emit_block_move (blktramp, initial_trampoline,
! 		       GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
  #endif
        INITIALIZE_TRAMPOLINE (tramp, XEXP (DECL_RTL (function), 0), context);
        seq = get_insns ();
Index: gcc/config/sh/sh.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.c,v
retrieving revision 1.171
diff -c -p -d -r1.171 sh.c
*** gcc/config/sh/sh.c	28 Aug 2002 17:37:54 -0000	1.171
--- gcc/config/sh/sh.c	29 Aug 2002 19:08:49 -0000
*************** sh_initialize_trampoline (tramp, fnaddr,
*** 7301,7307 ****
        src = gen_rtx_MEM (BLKmode, tramp_templ);
        set_mem_align (dst, 256);
        set_mem_align (src, 64);
!       emit_block_move (dst, src, GEN_INT (fixed_len));
  
        emit_move_insn (gen_rtx_MEM (Pmode, plus_constant (tramp,	fixed_len)),
  		      fnaddr);
--- 7301,7307 ----
        src = gen_rtx_MEM (BLKmode, tramp_templ);
        set_mem_align (dst, 256);
        set_mem_align (src, 64);
!       emit_block_move (dst, src, GEN_INT (fixed_len), BLOCK_OP_NORMAL);
  
        emit_move_insn (gen_rtx_MEM (Pmode, plus_constant (tramp,	fixed_len)),
  		      fnaddr);
Index: gcc/config/sparc/sparc.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sparc/sparc.c,v
retrieving revision 1.226
diff -c -p -d -r1.226 sparc.c
*** gcc/config/sparc/sparc.c	16 Jul 2002 20:59:06 -0000	1.226
--- gcc/config/sparc/sparc.c	29 Aug 2002 19:08:49 -0000
*************** sparc_va_arg (valist, type)
*** 5347,5353 ****
        PUT_MODE (tmp, BLKmode);
        set_mem_alias_set (tmp, 0);
        
!       dest_addr = emit_block_move (tmp, addr_rtx, GEN_INT (rsize));
        if (dest_addr != NULL_RTX)
  	addr_rtx = dest_addr;
        else
--- 5347,5354 ----
        PUT_MODE (tmp, BLKmode);
        set_mem_alias_set (tmp, 0);
        
!       dest_addr = emit_block_move (tmp, addr_rtx, GEN_INT (rsize),
! 				   BLOCK_OP_NORMAL);
        if (dest_addr != NULL_RTX)
  	addr_rtx = dest_addr;
        else


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