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]

Re: [patches] Re: x86_64 merger part 17 - split-long-move update


> 
> I'd prefer you used change_address instead of PUT_MODE throughout.
> I know that existing code in this function does it, but I don't
> like that either.
> 
> Again, please use UNITS_PER_WORD.  It's more concise than the
> explicit conditional, and it documents exactly what you want.
> 
> > +       /* 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)
> 
> This part is confusingly arranged with multiple tests for TARGET_64BIT.
> 
> >     [(const_int 0)]
> > !   "ix86_split_long_move (operands);")
> 
> You've lost the DONE.

Hi
I am just testing following updated version of the patch. OK assuming
that it passes bootstrap/testsuite?

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: i386-protos.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/i386/i386-protos.h,v
retrieving revision 1.46
diff -c -3 -p -r1.46 i386-protos.h
*** i386-protos.h	2001/03/21 10:12:19	1.46
--- i386-protos.h	2001/03/21 10:26:50
*************** extern void ix86_expand_branch PARAMS ((
*** 115,121 ****
  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));
--- 115,121 ----
  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: i386.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/i386/i386.c,v
retrieving revision 1.237
diff -c -3 -p -r1.237 i386.c
*** i386.c	2001/03/21 10:12:19	1.237
--- i386.c	2001/03/21 10:27:01
*************** ix86_split_to_parts (operand, parts, mod
*** 6579,6588 ****
        if (! push_operand (operand, VOIDmode))
  	abort ();
  
!       PUT_MODE (operand, SImode);
        parts[0] = parts[1] = parts[2] = operand;
      }
!   else
      {
        if (mode == DImode)
  	split_di (&operand, 1, &parts[0], &parts[1]);
--- 6579,6588 ----
        if (! push_operand (operand, VOIDmode))
  	abort ();
  
!       operand = change_address (operand, SImode, operand);
        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
*** 6599,6605 ****
  	    }
  	  else if (offsettable_memref_p (operand))
  	    {
! 	      PUT_MODE (operand, SImode);
  	      parts[0] = operand;
  	      parts[1] = adj_offsettable_operand (operand, 4);
  	      if (size == 3)
--- 6599,6605 ----
  	    }
  	  else if (offsettable_memref_p (operand))
  	    {
! 	      operand = change_address (operand, SImode, operand);
  	      parts[0] = operand;
  	      parts[1] = adj_offsettable_operand (operand, 4);
  	      if (size == 3)
*************** ix86_split_to_parts (operand, parts, mod
*** 6631,6636 ****
--- 6631,6672 ----
  	    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))
+ 	    {
+ 	      operand = change_address (operand, DImode, operand);
+ 	      parts[0] = operand;
+ 	      parts[1] = adj_offsettable_operand (operand, 8);
+ 	      parts[1] = change_address (parts[1], SImode, operand);
+ 	    }
+ 	  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
*** 6640,6655 ****
     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]);
--- 6676,6717 ----
     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 i386.md splitters.  */
+   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]);
+ 	  operands[0] = change_address (operands[0], DImode, operands[0]);
+ 	}
+       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)
*** 6661,6674 ****
  	   && ! 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];
      }
--- 6723,6736 ----
  	   && ! 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)
*** 6681,6692 ****
  	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;
--- 6743,6754 ----
  	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)
*** 6699,6740 ****
        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];
--- 6761,6825 ----
        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],
! 					        UNITS_PER_WORD);
! 	  part[1][1] = change_address (part[1][1], SImode, part[1][1]);
! 	  if (nparts == 3)
  	    part[1][2] = adj_offsettable_operand (part[1][0], 8);
  	}
      }
  
    if (push)
      {
!       if (!TARGET_64BIT)
! 	{
! 	  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]));
! 	    }
! 	}
!       else
  	{
! 	  /* 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 (GET_MODE (part[1][1]) == SImode)
! 	    {
! 	      if (GET_CODE (part[1][1]) == MEM)
! 		part[1][1] = change_address (part[1][1], DImode, part[1][1]);
! 	      else if (REG_P (part[1][1]))
! 		part[1][1] = gen_rtx_REG (DImode, REGNO (part[1][1]));
! 	      else
! 		abort();
! 	    }
  	}
        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)
*** 6753,6759 ****
      }
    else
      {
!       if (size == 3)
  	{
  	  operands1[2] = part[0][0];
  	  operands1[3] = part[0][1];
--- 6838,6844 ----
      }
    else
      {
!       if (nparts == 3)
  	{
  	  operands1[2] = part[0][0];
  	  operands1[3] = part[0][1];
*************** ix86_split_long_move (operands1)
*** 6770,6777 ****
  	  operands1[6] = part[1][1];
  	}
      }
  
!   return 0;
  }
  
  void
--- 6855,6873 ----
  	  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: i386.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/i386/i386.md,v
retrieving revision 1.240
diff -c -3 -p -r1.240 i386.md
*** i386.md	2001/03/21 10:12:20	1.240
--- i386.md	2001/03/21 10:27:17
***************
*** 2177,2192 ****
          (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" "")
--- 2177,2191 ----
          (match_operand:DI 1 "general_operand" ""))]
    "reload_completed && ! MMX_REG_P (operands[1]) && !TARGET_64BIT"
    [(const_int 0)]
!   "ix86_split_long_move (operands); 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])"
!   [(const_int 0)]
!   "ix86_split_long_move (operands); DONE;")
    
  (define_expand "movsf"
    [(set (match_operand:SF 0 "nonimmediate_operand" "")
***************
*** 2401,2407 ****
  	(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
--- 2400,2406 ----
  	(match_operand:DF 1 "general_operand" ""))]
    "reload_completed"
    [(const_int 0)]
!   "ix86_split_long_move (operands); DONE;")
  
  ;; Moving is usually shorter when only FP registers are used. This separate
  ;; movdf pattern avoids the use of integer registers for FP operations
***************
*** 2535,2543 ****
     && ! (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")
--- 2534,2541 ----
     && ! (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); DONE;")
  
  (define_insn "*swapdf"
    [(set (match_operand:DF 0 "register_operand" "+f")
***************
*** 2697,2703 ****
         || 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" "")
--- 2695,2701 ----
         || GET_MODE (operands[0]) == DFmode)
     && (!REG_P (operands[1]) || !ANY_FP_REGNO_P (REGNO (operands[1])))"
    [(const_int 0)]
!   "ix86_split_long_move (operands); DONE;")
  
  (define_split
    [(set (match_operand:XF 0 "push_operand" "")
***************
*** 2916,2925 ****
     && ! (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" "")
--- 2914,2921 ----
     && ! (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); DONE;")
  
  (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]