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 17 - split-long-move update



Hi
Another nontrivial part that can get in before push issues are settled down.
It updates split_long_move to support 64bit moves.
This need updating on splitters part, since number of moves produced by
split_long_move is no longer fixed.

The ifdef is needed to avoid warning.

Quite unfortunate complication is that I handle moving of TFmodes by
64bit move followed by cheaper 32bit move.  This adds kind of
"ping pong" with modes later in the code, since for example if
I am splitting push, it should be both 64bits anyway.

Honza

Wed Mar 14 18:51:04 CET 2001  Jan Hubicka  <jh@suse.cz>
	* i386-protos.h (ix86_split_long_move): Return void.
	* i386.c (ix86_split_to_parts): Handle 64bit target.
	(ix86_split_long_move): Likewise.
	* i386.md (all calls to ix86_split_long_move): Update.
Index: egcs/gcc/config/i386/i386-protos.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/i386/i386-protos.h,v
retrieving revision 1.44
diff -c -3 -p -r1.44 i386-protos.h
*** i386-protos.h	2001/02/28 18:19:22	1.44
--- i386-protos.h	2001/03/14 17:50:37
*************** extern void ix86_expand_branch PARAMS ((
*** 109,115 ****
  extern int ix86_expand_setcc PARAMS ((enum rtx_code, rtx));
  extern int ix86_expand_int_movcc PARAMS ((rtx[]));
  extern int ix86_expand_fp_movcc PARAMS ((rtx[]));
! extern int ix86_split_long_move PARAMS ((rtx[]));
  extern void ix86_split_ashldi PARAMS ((rtx *, rtx));
  extern void ix86_split_ashrdi PARAMS ((rtx *, rtx));
  extern void ix86_split_lshrdi PARAMS ((rtx *, rtx));
--- 109,115 ----
  extern int ix86_expand_setcc PARAMS ((enum rtx_code, rtx));
  extern int ix86_expand_int_movcc PARAMS ((rtx[]));
  extern int ix86_expand_fp_movcc PARAMS ((rtx[]));
! extern void ix86_split_long_move PARAMS ((rtx[]));
  extern void ix86_split_ashldi PARAMS ((rtx *, rtx));
  extern void ix86_split_ashrdi PARAMS ((rtx *, rtx));
  extern void ix86_split_lshrdi PARAMS ((rtx *, rtx));
Index: egcs/gcc/config/i386/i386.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/i386/i386.c,v
retrieving revision 1.234
diff -c -3 -p -r1.234 i386.c
*** i386.c	2001/03/12 15:31:51	1.234
--- i386.c	2001/03/14 17:50:40
*************** ix86_split_to_parts (operand, parts, mod
*** 6283,6289 ****
        PUT_MODE (operand, SImode);
        parts[0] = parts[1] = parts[2] = operand;
      }
!   else
      {
        if (mode == DImode)
  	split_di (&operand, 1, &parts[0], &parts[1]);
--- 6283,6289 ----
        PUT_MODE (operand, SImode);
        parts[0] = parts[1] = parts[2] = operand;
      }
!   else if (!TARGET_64BIT)
      {
        if (mode == DImode)
  	split_di (&operand, 1, &parts[0], &parts[1]);
*************** ix86_split_to_parts (operand, parts, mod
*** 6332,6337 ****
--- 6332,6373 ----
  	    abort ();
  	}
      }
+   else
+     {
+       if (mode == XFmode || mode == TFmode)
+ 	{
+ 	  if (REG_P (operand))
+ 	    {
+ 	      if (!reload_completed)
+ 		abort ();
+ 	      parts[0] = gen_rtx_REG (DImode, REGNO (operand) + 0);
+ 	      parts[1] = gen_rtx_REG (SImode, REGNO (operand) + 1);
+ 	    }
+ 	  else if (offsettable_memref_p (operand))
+ 	    {
+ 	      PUT_MODE (operand, DImode);
+ 	      parts[0] = operand;
+ 	      parts[1] = adj_offsettable_operand (operand, 8);
+ 	      PUT_MODE (parts[1], SImode);
+ 	    }
+ 	  else if (GET_CODE (operand) == CONST_DOUBLE)
+ 	    {
+ 	      REAL_VALUE_TYPE r;
+ 	      long l[3];
+ 
+ 	      REAL_VALUE_FROM_CONST_DOUBLE (r, operand);
+ 	      REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, l);
+ #if HOST_BITS_PER_WIDE_INT >= 64
+ 	      parts[0] = GEN_INT (l[0] + (l[1] << 32));
+ #else
+ 	      parts[0] = immed_double_const (l[0], l[1], DImode);
+ #endif
+ 	      parts[1] = GEN_INT (l[2]);
+ 	    }
+ 	  else
+ 	    abort ();
+ 	}
+     }
  
    return size;
  }
*************** ix86_split_to_parts (operand, parts, mod
*** 6341,6356 ****
     insns have been emitted.  Operands 2-4 contain the input values
     int the correct order; operands 5-7 contain the output values.  */
  
! int
  ix86_split_long_move (operands1)
       rtx operands1[];
  {
    rtx part[2][3];
    rtx operands[2];
!   int size;
    int push = 0;
    int collisions = 0;
  
    /* Make our own copy to avoid clobbering the operands.  */
    operands[0] = copy_rtx (operands1[0]);
    operands[1] = copy_rtx (operands1[1]);
--- 6377,6418 ----
     insns have been emitted.  Operands 2-4 contain the input values
     int the correct order; operands 5-7 contain the output values.  */
  
! void
  ix86_split_long_move (operands1)
       rtx operands1[];
  {
    rtx part[2][3];
    rtx operands[2];
!   int nparts;
    int push = 0;
    int collisions = 0;
  
+   /* The DFmode expanders may ask us to move double.
+      For 64bit target this is single move.  By hiding the fact
+      here we simplify somehow i386.md part.  */
+   if (GET_MODE_SIZE (GET_MODE (operands1[0])) == 8 && TARGET_64BIT)
+     {
+       /* Optimize constant pool reference to immediates.  This is used by fp moves,
+ 	 that force all constants to memory to allow combining.  */
+ 
+       if (GET_CODE (operands1[1]) == MEM
+ 	  && GET_CODE (XEXP (operands1[1], 0)) == SYMBOL_REF
+ 	  && CONSTANT_POOL_ADDRESS_P (XEXP (operands1[1], 0)))
+ 	operands[1] = get_pool_constant (XEXP (operands1[1], 0));
+       else
+ 	operands[1] = operands1[1];
+       if (push_operand (operands1[0], VOIDmode))
+ 	{
+           operands[0] = copy_rtx (operands1[0]);
+ 	  PUT_MODE (operands[0], DImode);
+ 	}
+       else
+         operands[0] = gen_lowpart (DImode, operands1[0]);
+       operands[1] = gen_lowpart (DImode, operands[1]);
+       emit_move_insn (operands[0], operands[1]);
+       return;
+     }
+ 
    /* Make our own copy to avoid clobbering the operands.  */
    operands[0] = copy_rtx (operands1[0]);
    operands[1] = copy_rtx (operands1[1]);
*************** ix86_split_long_move (operands1)
*** 6362,6375 ****
  	   && ! offsettable_memref_p (operands[0]))
      abort ();
  
!   size = ix86_split_to_parts (operands[0], part[0], GET_MODE (operands1[0]));
!   ix86_split_to_parts (operands[1], part[1], GET_MODE (operands1[0]));
  
    /* When emitting push, take care for source operands on the stack.  */
    if (push && GET_CODE (operands[1]) == MEM
        && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
      {
!       if (size == 3)
  	part[1][1] = part[1][2];
        part[1][0] = part[1][1];
      }
--- 6424,6437 ----
  	   && ! offsettable_memref_p (operands[0]))
      abort ();
  
!   nparts = ix86_split_to_parts (operands[1], part[1], GET_MODE (operands1[0]));
!   ix86_split_to_parts (operands[0], part[0], GET_MODE (operands1[0]));
  
    /* When emitting push, take care for source operands on the stack.  */
    if (push && GET_CODE (operands[1]) == MEM
        && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
      {
!       if (nparts == 3)
  	part[1][1] = part[1][2];
        part[1][0] = part[1][1];
      }
*************** ix86_split_long_move (operands1)
*** 6382,6393 ****
  	collisions++;
        if (reg_overlap_mentioned_p (part[0][1], XEXP (part[1][0], 0)))
  	collisions++;
!       if (size == 3
  	  && reg_overlap_mentioned_p (part[0][2], XEXP (part[1][0], 0)))
  	collisions++;
  
        /* Collision in the middle part can be handled by reordering.  */
!       if (collisions == 1 && size == 3
  	  && reg_overlap_mentioned_p (part[0][1], XEXP (part[1][0], 0)))
  	{
  	  rtx tmp;
--- 6444,6455 ----
  	collisions++;
        if (reg_overlap_mentioned_p (part[0][1], XEXP (part[1][0], 0)))
  	collisions++;
!       if (nparts == 3
  	  && reg_overlap_mentioned_p (part[0][2], XEXP (part[1][0], 0)))
  	collisions++;
  
        /* Collision in the middle part can be handled by reordering.  */
!       if (collisions == 1 && nparts == 3
  	  && reg_overlap_mentioned_p (part[0][1], XEXP (part[1][0], 0)))
  	{
  	  rtx tmp;
*************** ix86_split_long_move (operands1)
*** 6400,6441 ****
        else if (collisions > 1)
  	{
  	  collisions = 1;
! 	  emit_insn (gen_rtx_SET (VOIDmode, part[0][size - 1],
  				  XEXP (part[1][0], 0)));
! 	  part[1][0] = change_address (part[1][0], SImode, part[0][size - 1]);
! 	  part[1][1] = adj_offsettable_operand (part[1][0], 4);
! 	  if (size == 3)
  	    part[1][2] = adj_offsettable_operand (part[1][0], 8);
  	}
      }
  
    if (push)
      {
!       if (size == 3)
  	{
  	  /* We use only first 12 bytes of TFmode value, but for pushing we
  	     are required to adjust stack as if we were pushing real 16byte
  	     value.  */
! 	  if (GET_MODE (operands1[0]) == TFmode)
  	    emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
  				   GEN_INT (-4)));
  	  emit_insn (gen_push (part[1][2]));
  	}
        emit_insn (gen_push (part[1][1]));
        emit_insn (gen_push (part[1][0]));
!       return 1;
      }
  
    /* Choose correct order to not overwrite the source before it is copied.  */
    if ((REG_P (part[0][0])
         && REG_P (part[1][1])
         && (REGNO (part[0][0]) == REGNO (part[1][1])
! 	   || (size == 3
  	       && REGNO (part[0][0]) == REGNO (part[1][2]))))
        || (collisions > 0
  	  && reg_overlap_mentioned_p (part[0][0], XEXP (part[1][0], 0))))
      {
!       if (size == 3)
  	{
  	  operands1[2] = part[0][2];
  	  operands1[3] = part[0][1];
--- 6462,6520 ----
        else if (collisions > 1)
  	{
  	  collisions = 1;
! 	  emit_insn (gen_rtx_SET (VOIDmode, part[0][nparts - 1],
  				  XEXP (part[1][0], 0)));
! 	  part[1][0] = change_address (part[1][0],
! 				       TARGET_64BIT ? DImode : SImode,
! 				       part[0][nparts - 1]);
! 	  part[1][1] = adj_offsettable_operand (part[1][0],
! 					        TARGET_64BIT ? 8 : 4);
! 	  PUT_MODE (part[1][1], SImode);
! 	  if (nparts == 3)
  	    part[1][2] = adj_offsettable_operand (part[1][0], 8);
  	}
      }
  
    if (push)
      {
!       if (nparts == 3)
  	{
  	  /* We use only first 12 bytes of TFmode value, but for pushing we
  	     are required to adjust stack as if we were pushing real 16byte
  	     value.  */
! 	  if (GET_MODE (operands1[0]) == TFmode && !TARGET_64BIT)
  	    emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
  				   GEN_INT (-4)));
  	  emit_insn (gen_push (part[1][2]));
  	}
+       /* In 64bit mode we don't have 32bit push available.  In case this is
+ 	 register, it is OK - we will just use larger counterpart.  We also
+ 	 retype memory - these comes from attempt to avoid REX prefix on
+ 	 moving of second half of TFmode value.  */
+       if (TARGET_64BIT && GET_MODE (part[1][1]) == SImode)
+ 	{
+ 	  if (GET_CODE (part[1][1]) == MEM)
+ 	    PUT_MODE (part[1][1], DImode);
+ 	  else if (!REG_P (part[1][1]))
+ 	    abort();
+ 	  else
+ 	    part[1][1] = gen_rtx_REG (DImode, REGNO (part[1][1]));
+ 	}
        emit_insn (gen_push (part[1][1]));
        emit_insn (gen_push (part[1][0]));
!       return;
      }
  
    /* Choose correct order to not overwrite the source before it is copied.  */
    if ((REG_P (part[0][0])
         && REG_P (part[1][1])
         && (REGNO (part[0][0]) == REGNO (part[1][1])
! 	   || (nparts == 3
  	       && REGNO (part[0][0]) == REGNO (part[1][2]))))
        || (collisions > 0
  	  && reg_overlap_mentioned_p (part[0][0], XEXP (part[1][0], 0))))
      {
!       if (nparts == 3)
  	{
  	  operands1[2] = part[0][2];
  	  operands1[3] = part[0][1];
*************** ix86_split_long_move (operands1)
*** 6454,6460 ****
      }
    else
      {
!       if (size == 3)
  	{
  	  operands1[2] = part[0][0];
  	  operands1[3] = part[0][1];
--- 6533,6539 ----
      }
    else
      {
!       if (nparts == 3)
  	{
  	  operands1[2] = part[0][0];
  	  operands1[3] = part[0][1];
*************** ix86_split_long_move (operands1)
*** 6471,6478 ****
  	  operands1[6] = part[1][1];
  	}
      }
  
!   return 0;
  }
  
  void
--- 6550,6568 ----
  	  operands1[6] = part[1][1];
  	}
      }
+   if (nparts == 3)
+     {
+       emit_move_insn (operands1[2], operands1[5]);
+       emit_move_insn (operands1[3], operands1[6]);
+       emit_move_insn (operands1[4], operands1[7]);
+     }
+   else
+     {
+       emit_move_insn (operands1[2], operands1[5]);
+       emit_move_insn (operands1[3], operands1[6]);
+     }
  
!   return;
  }
  
  void
Index: egcs/gcc/config/i386/i386.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/i386/i386.md,v
retrieving revision 1.236
diff -c -3 -p -r1.236 i386.md
*** i386.md	2001/03/14 15:38:55	1.236
--- i386.md	2001/03/14 17:50:42
***************
*** 2197,2212 ****
          (match_operand:DI 1 "general_operand" ""))]
    "reload_completed && ! MMX_REG_P (operands[1]) && !TARGET_64BIT"
    [(const_int 0)]
!   "if (!ix86_split_long_move (operands)) abort (); DONE;")
  
  ;; %%% This multiword shite has got to go.
  (define_split
    [(set (match_operand:DI 0 "nonimmediate_operand" "")
          (match_operand:DI 1 "general_operand" ""))]
    "reload_completed && ! MMX_REG_P (operands[0]) && ! MMX_REG_P (operands[1])"
!   [(set (match_dup 2) (match_dup 5))
!    (set (match_dup 3) (match_dup 6))]
!   "if (ix86_split_long_move (operands)) DONE;")
    
  (define_expand "movsf"
    [(set (match_operand:SF 0 "nonimmediate_operand" "")
--- 2197,2211 ----
          (match_operand:DI 1 "general_operand" ""))]
    "reload_completed && ! MMX_REG_P (operands[1]) && !TARGET_64BIT"
    [(const_int 0)]
!   "ix86_split_long_move (operands);")
  
  ;; %%% This multiword shite has got to go.
  (define_split
    [(set (match_operand:DI 0 "nonimmediate_operand" "")
          (match_operand:DI 1 "general_operand" ""))]
    "reload_completed && ! MMX_REG_P (operands[0]) && ! MMX_REG_P (operands[1])"
!   [(const_int 0)]
!   "ix86_split_long_move (operands);")
    
  (define_expand "movsf"
    [(set (match_operand:SF 0 "nonimmediate_operand" "")
***************
*** 2421,2427 ****
  	(match_operand:DF 1 "general_operand" ""))]
    "reload_completed"
    [(const_int 0)]
!   "if (!ix86_split_long_move (operands)) abort (); DONE;")
  
  ;; Moving is usually shorter when only FP registers are used. This separate
  ;; movdf pattern avoids the use of integer registers for FP operations
--- 2420,2426 ----
  	(match_operand:DF 1 "general_operand" ""))]
    "reload_completed"
    [(const_int 0)]
!   "ix86_split_long_move (operands);")
  
  ;; Moving is usually shorter when only FP registers are used. This separate
  ;; movdf pattern avoids the use of integer registers for FP operations
***************
*** 2555,2563 ****
     && ! (ANY_FP_REG_P (operands[1]) || 
  	 (GET_CODE (operands[1]) == SUBREG
  	  && ANY_FP_REG_P (SUBREG_REG (operands[1]))))"
!   [(set (match_dup 2) (match_dup 5))
!    (set (match_dup 3) (match_dup 6))]
!   "if (ix86_split_long_move (operands)) DONE;")
  
  (define_insn "*swapdf"
    [(set (match_operand:DF 0 "register_operand" "+f")
--- 2554,2561 ----
     && ! (ANY_FP_REG_P (operands[1]) || 
  	 (GET_CODE (operands[1]) == SUBREG
  	  && ANY_FP_REG_P (SUBREG_REG (operands[1]))))"
!   [(const_int 0)]
!   "ix86_split_long_move (operands);")
  
  (define_insn "*swapdf"
    [(set (match_operand:DF 0 "register_operand" "+f")
***************
*** 2717,2723 ****
         || GET_MODE (operands[0]) == DFmode)
     && (!REG_P (operands[1]) || !ANY_FP_REGNO_P (REGNO (operands[1])))"
    [(const_int 0)]
!   "if (!ix86_split_long_move (operands)) abort (); DONE;")
  
  (define_split
    [(set (match_operand:XF 0 "push_operand" "")
--- 2715,2721 ----
         || GET_MODE (operands[0]) == DFmode)
     && (!REG_P (operands[1]) || !ANY_FP_REGNO_P (REGNO (operands[1])))"
    [(const_int 0)]
!   "ix86_split_long_move (operands);")
  
  (define_split
    [(set (match_operand:XF 0 "push_operand" "")
***************
*** 2936,2945 ****
     && ! (ANY_FP_REG_P (operands[1]) || 
  	 (GET_CODE (operands[1]) == SUBREG
  	  && ANY_FP_REG_P (SUBREG_REG (operands[1]))))"
!   [(set (match_dup 2) (match_dup 5))
!    (set (match_dup 3) (match_dup 6))
!    (set (match_dup 4) (match_dup 7))]
!   "if (ix86_split_long_move (operands)) DONE;")
  
  (define_split
    [(set (match_operand 0 "register_operand" "")
--- 2934,2941 ----
     && ! (ANY_FP_REG_P (operands[1]) || 
  	 (GET_CODE (operands[1]) == SUBREG
  	  && ANY_FP_REG_P (SUBREG_REG (operands[1]))))"
!   [(const_int 0)]
!   "ix86_split_long_move (operands);")
  
  (define_split
    [(set (match_operand 0 "register_operand" "")


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