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]

x86_64 merger part 12 - change representation of push instructions


Hi,
this patch makes expr.c to change representation of push instructions where
PUSH_ROUNDING (size) != size.  Currently we use PRE_DEC/PRE_INC, that is
assumed in other code to always change by size.  This brings numberous
misscompilations when target decide to use them.

The patch also changes the push emitting machinery to always use
emit_single_push_insn, instead of emiting pushes by emit_move_insn.  This makes
possible to use in future pushM expanders instead of getting everything trought
moves.

I've sent the patch previously, but you've wondered if it breaks other
targets or not.  I believe it don't, as mentioned in other email, since all
those targets eigther
1) define PUSH_ROUDING to size
2) are 32bit and promote everything to integers, so like on i386, the push
   operations with smaller sizes are unused except for passing complex numbers
   I care in separate patch.

Honza

Mon Mar 12 15:47:53 CET 2001  Jan Hubicka  <jh@suse.cz>
	* expr.c (emit_single_push_insn): New function.
	(move_by_pieces): Accept NULL as destination for push instructions.
	(gen_push_operand): Kill.
	(emit_push_insn): Pass NULL when pushing; avoid updating of
	stack_pointer_delta.
	* expr.h (gen_push_operand): Kill.
*** expr.c	Sat Mar  3 19:30:30 2001
--- /home/hubicka/x86-64/gcc/gcc/expr.c	Tue Mar  6 19:30:44 2001
*************** static void do_jump_by_parts_equality PA
*** 187,192 ****
--- 187,193 ----
  static void do_compare_and_jump	PARAMS ((tree, enum rtx_code, enum rtx_code,
  					 rtx, rtx));
  static rtx do_store_flag	PARAMS ((tree, rtx, enum machine_mode, int));
+ static void emit_single_push_insn PARAMS ((enum machine_mode, rtx, tree));
  
  /* Record for each mode whether we can move a register directly to or
     from an object of that mode in memory.  If we can't, we won't try
*************** convert_modes (mode, oldmode, x, unsigne
*** 1400,1405 ****
--- 1401,1410 ----
     from block FROM to block TO.  (These are MEM rtx's with BLKmode).
     The caller must pass FROM and TO
      through protect_from_queue before calling.
+ 
+    When TO is NULL, the emit_single_push_insn is used to push the
+    FROM to stack.
+ 
     ALIGN is maximum alignment we can assume.  */
  
  void
*************** move_by_pieces (to, from, len, align)
*** 1409,1427 ****
       unsigned int align;
  {
    struct move_by_pieces data;
!   rtx to_addr = XEXP (to, 0), from_addr = XEXP (from, 0);
    unsigned int max_size = MOVE_MAX_PIECES + 1;
    enum machine_mode mode = VOIDmode, tmode;
    enum insn_code icode;
  
    data.offset = 0;
-   data.to_addr = to_addr;
    data.from_addr = from_addr;
!   data.to = to;
    data.from = from;
-   data.autinc_to
-     = (GET_CODE (to_addr) == PRE_INC || GET_CODE (to_addr) == PRE_DEC
-        || GET_CODE (to_addr) == POST_INC || GET_CODE (to_addr) == POST_DEC);
    data.autinc_from
      = (GET_CODE (from_addr) == PRE_INC || GET_CODE (from_addr) == PRE_DEC
         || GET_CODE (from_addr) == POST_INC
--- 1414,1449 ----
       unsigned int align;
  {
    struct move_by_pieces data;
!   rtx to_addr, from_addr = XEXP (from, 0);
    unsigned int max_size = MOVE_MAX_PIECES + 1;
    enum machine_mode mode = VOIDmode, tmode;
    enum insn_code icode;
  
    data.offset = 0;
    data.from_addr = from_addr;
!   if (to)
!     {
!       to_addr = XEXP (to, 0);
!       data.to = to;
!       data.autinc_to
! 	= (GET_CODE (to_addr) == PRE_INC || GET_CODE (to_addr) == PRE_DEC
! 	   || GET_CODE (to_addr) == POST_INC || GET_CODE (to_addr) == POST_DEC);
!       data.reverse
! 	= (GET_CODE (to_addr) == PRE_DEC || GET_CODE (to_addr) == POST_DEC);
!     }
!   else
!     {
!       to_addr = NULL_RTX;
!       data.to = NULL_RTX;
!       data.autinc_to = 1;
! #ifdef STACK_GROWS_DOWNWARD
!       data.reverse = 1;
! #else
!       data.reverse = 0;
! #endif
!     }
!   data.to_addr = to_addr;
    data.from = from;
    data.autinc_from
      = (GET_CODE (from_addr) == PRE_INC || GET_CODE (from_addr) == PRE_DEC
         || GET_CODE (from_addr) == POST_INC
*************** move_by_pieces (to, from, len, align)
*** 1429,1436 ****
  
    data.explicit_inc_from = 0;
    data.explicit_inc_to = 0;
-   data.reverse
-     = (GET_CODE (to_addr) == PRE_DEC || GET_CODE (to_addr) == POST_DEC);
    if (data.reverse) data.offset = len;
    data.len = len;
  
--- 1451,1456 ----
*************** move_by_pieces_1 (genfun, mode, data)
*** 1563,1576 ****
        if (data->reverse)
  	data->offset -= size;
  
!       if (data->autinc_to)
  	{
! 	  to1 = gen_rtx_MEM (mode, data->to_addr);
! 	  MEM_COPY_ATTRIBUTES (to1, data->to);
  	}
-       else
- 	to1 = change_address (data->to, mode,
- 			      plus_constant (data->to_addr, data->offset));
  
        if (data->autinc_from)
  	{
--- 1583,1599 ----
        if (data->reverse)
  	data->offset -= size;
  
!       if (data->to)
  	{
! 	  if (data->autinc_to)
! 	    {
! 	      to1 = gen_rtx_MEM (mode, data->to_addr);
! 	      MEM_COPY_ATTRIBUTES (to1, data->to);
! 	    }
! 	  else
! 	    to1 = change_address (data->to, mode,
! 				  plus_constant (data->to_addr, data->offset));
  	}
  
        if (data->autinc_from)
  	{
*************** move_by_pieces_1 (genfun, mode, data)
*** 1586,1592 ****
        if (HAVE_PRE_DECREMENT && data->explicit_inc_from < 0)
  	emit_insn (gen_add2_insn (data->from_addr, GEN_INT (-size)));
  
!       emit_insn ((*genfun) (to1, from1));
  
        if (HAVE_POST_INCREMENT && data->explicit_inc_to > 0)
  	emit_insn (gen_add2_insn (data->to_addr, GEN_INT (size)));
--- 1609,1618 ----
        if (HAVE_PRE_DECREMENT && data->explicit_inc_from < 0)
  	emit_insn (gen_add2_insn (data->from_addr, GEN_INT (-size)));
  
!       if (data->to)
! 	emit_insn ((*genfun) (to1, from1));
!       else
! 	emit_single_push_insn (mode, from1, NULL);
  
        if (HAVE_POST_INCREMENT && data->explicit_inc_to > 0)
  	emit_insn (gen_add2_insn (data->to_addr, GEN_INT (size)));
*************** push_block (size, extra, below)
*** 3045,3055 ****
    return memory_address (GET_CLASS_NARROWEST_MODE (MODE_INT), temp);
  }
  
- rtx
- gen_push_operand ()
- {
-   return gen_rtx_fmt_e (STACK_PUSH_CODE, Pmode, stack_pointer_rtx);
- }
  
  /* Return an rtx for the address of the beginning of a as-if-it-was-pushed
     block of SIZE bytes.  */
--- 3071,3076 ----
*************** get_push_address (size)
*** 3070,3075 ****
--- 3091,3141 ----
    return copy_to_reg (temp);
  }
  
+ /* Emit single push insn.  */
+ static void
+ emit_single_push_insn (mode, x, type)
+      rtx x;
+      enum machine_mode mode;
+      tree type;
+ {
+ #ifdef PUSH_ROUNDING
+   rtx dest_addr;
+   int rounded_size = PUSH_ROUNDING (GET_MODE_SIZE (mode));
+   rtx dest;
+ 
+   if (GET_MODE_SIZE (mode) == rounded_size)
+     dest_addr = gen_rtx_fmt_e (STACK_PUSH_CODE, Pmode, stack_pointer_rtx);
+   else
+     {
+ #ifdef STACK_GROWS_DOWNWARD
+       dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
+ 				GEN_INT (-rounded_size));
+ #else
+       dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
+ 				GEN_INT (rounded_size));
+ #endif
+       dest_addr = gen_rtx_PRE_MODIFY (Pmode, stack_pointer_rtx, dest_addr);
+     }
+ 
+   dest = gen_rtx_MEM (mode, dest_addr);
+ 
+   stack_pointer_delta += PUSH_ROUNDING (GET_MODE_SIZE (mode));
+ 
+   if (type != 0)
+     {
+       set_mem_attributes (dest, type, 1);
+       /* Function incoming arguments may overlap with sibling call
+          outgoing arguments and we cannot allow reordering of reads
+          from function arguments with stores to outgoing arguments
+          of sibling calls.  */
+       MEM_ALIAS_SET (dest) = 0;
+     }
+   emit_move_insn (dest, x);
+ #else
+   abort();
+ #endif
+ }
+ 
  /* Generate code to push X onto the stack, assuming it has mode MODE and
     type TYPE.
     MODE is redundant except when X is a CONST_INT (since they don't
*************** emit_push_insn (x, mode, type, size, ali
*** 3190,3198 ****
  	      && where_pad != none && where_pad != stack_direction)
  	    anti_adjust_stack (GEN_INT (extra));
  
! 	  stack_pointer_delta += INTVAL (size) - used;
! 	  move_by_pieces (gen_rtx_MEM (BLKmode, gen_push_operand ()), xinner,
! 			  INTVAL (size) - used, align);
  
  	  if (current_function_check_memory_usage && ! in_check_memory_usage)
  	    {
--- 3256,3262 ----
  	      && where_pad != none && where_pad != stack_direction)
  	    anti_adjust_stack (GEN_INT (extra));
  
! 	  move_by_pieces (NULL, xinner, INTVAL (size) - used, align);
  
  	  if (current_function_check_memory_usage && ! in_check_memory_usage)
  	    {
*************** emit_push_insn (x, mode, type, size, ali
*** 3444,3453 ****
  
  #ifdef PUSH_ROUNDING
        if (args_addr == 0 && PUSH_ARGS)
! 	{
! 	  addr = gen_push_operand ();
! 	  stack_pointer_delta += PUSH_ROUNDING (GET_MODE_SIZE (mode));
! 	}
        else
  #endif
  	{
--- 3508,3514 ----
  
  #ifdef PUSH_ROUNDING
        if (args_addr == 0 && PUSH_ARGS)
! 	emit_single_push_insn (mode, x, type);
        else
  #endif
  	{
*************** emit_push_insn (x, mode, type, size, ali
*** 3460,3479 ****
  	    addr = memory_address (mode, gen_rtx_PLUS (Pmode, args_addr,
  						       args_so_far));
  	  target = addr;
! 	}
  
!       dest = gen_rtx_MEM (mode, addr);
!       if (type != 0)
! 	{
! 	  set_mem_attributes (dest, type, 1);
! 	  /* Function incoming arguments may overlap with sibling call
! 	     outgoing arguments and we cannot allow reordering of reads
! 	     from function arguments with stores to outgoing arguments
! 	     of sibling calls.  */
! 	  MEM_ALIAS_SET (dest) = 0;
! 	}
  
!       emit_move_insn (dest, x);
  
        if (current_function_check_memory_usage && ! in_check_memory_usage)
  	{
--- 3521,3540 ----
  	    addr = memory_address (mode, gen_rtx_PLUS (Pmode, args_addr,
  						       args_so_far));
  	  target = addr;
! 	  dest = gen_rtx_MEM (mode, addr);
! 	  if (type != 0)
! 	    {
! 	      set_mem_attributes (dest, type, 1);
! 	      /* Function incoming arguments may overlap with sibling call
! 		 outgoing arguments and we cannot allow reordering of reads
! 		 from function arguments with stores to outgoing arguments
! 		 of sibling calls.  */
! 	      MEM_ALIAS_SET (dest) = 0;
! 	    }
  
! 	  emit_move_insn (dest, x);
  
! 	}
  
        if (current_function_check_memory_usage && ! in_check_memory_usage)
  	{
*** expr.h	Mon Dec  4 00:58:44 2000
--- /home/hubicka/x86-64/gcc/gcc/expr.h	Thu Dec  7 18:40:42 2000
*************** extern rtx emit_move_insn_1 PARAMS ((rtx
*** 1040,1048 ****
     and return an rtx to address the beginning of the block.  */
  extern rtx push_block PARAMS ((rtx, int, int));
  
- /* Make an operand to push something on the stack.  */
- extern rtx gen_push_operand PARAMS ((void));
- 
  #ifdef TREE_CODE
  /* Generate code to push something onto the stack, given its mode and type.  */
  extern void emit_push_insn PARAMS ((rtx, enum machine_mode, tree, rtx,
--- 1040,1045 ----


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