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]

TImode support for x86_64



Hi,
this patch adds support for moving TImode values around integer registers.  Bo
is working on patches to allow TImode arithmetic in x86_64, but this is not
ready yet.  This patch has turned out to be required to compile glibc, as we
already publish mulditi pattern and use it for parameter passing conventions.

Bootstrapped/regtested i686, regtested x86_64

Honza

Thu Oct  4 14:34:08 CEST 2001  Jan Hubicka  <jh@suse.cz>
	* i386.c (split_ti): New function.
	(split_di): Cleanup.
	(split_to_parts): Handle TImode split; fix XFmode packing.
	(VALID_INT_REG_MODE): Add TImode/CTImode.
	(movti_internal): Disable for 64bit
	(movti_rex64): New pattern and splitter.
Index: config/i386/i386.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.c,v
retrieving revision 1.314
diff -c -3 -p -r1.314 i386.c
*** i386.c	2001/10/02 10:59:38	1.314
--- i386.c	2001/10/04 12:14:57
*************** static rtx * ix86_pent_find_pair PARAMS 
*** 613,618 ****
--- 629,635 ----
  static void ix86_init_machine_status PARAMS ((struct function *));
  static void ix86_mark_machine_status PARAMS ((struct function *));
  static void ix86_free_machine_status PARAMS ((struct function *));
+ static void split_ti PARAMS ((rtx[], int, rtx[], rtx[]));
  static int ix86_split_to_parts PARAMS ((rtx, rtx *, enum machine_mode));
  static int ix86_safe_length_prefix PARAMS ((rtx));
  static int ix86_nsaved_regs PARAMS((void));
*************** split_di (operands, num, lo_half, hi_hal
*** 5907,5935 ****
    while (num--)
      {
        rtx op = operands[num];
!       if (CONSTANT_P (op))
! 	split_double (op, &lo_half[num], &hi_half[num]);
!       else if (! reload_completed)
  	{
! 	  lo_half[num] = gen_lowpart (SImode, op);
! 	  hi_half[num] = gen_highpart (SImode, op);
  	}
!       else if (GET_CODE (op) == REG)
  	{
! 	  if (TARGET_64BIT)
! 	    abort();
! 	  lo_half[num] = gen_rtx_REG (SImode, REGNO (op));
! 	  hi_half[num] = gen_rtx_REG (SImode, REGNO (op) + 1);
  	}
!       else if (offsettable_memref_p (op))
  	{
  	  lo_half[num] = adjust_address (op, SImode, 0);
! 	  hi_half[num] = adjust_address (op, SImode, 4);
  	}
        else
! 	abort ();
      }
  }
  
  /* Output code to perform a 387 binary operation in INSN, one of PLUS,
     MINUS, MULT or DIV.  OPERANDS are the insn operands, where operands[3]
--- 5924,5976 ----
    while (num--)
      {
        rtx op = operands[num];
!       /* simplify_subreg refuse to simplify subregs around
! 	 volatile memory accesses, but on i386 we need it.  */
!       if (GET_CODE (op) == MEM)
  	{
! 	  lo_half[num] = adjust_address (op, SImode, 0);
! 	  hi_half[num] = adjust_address (op, SImode, 4);
  	}
!       else
  	{
! 	  lo_half[num] = simplify_gen_subreg (SImode, op, DImode, 0);
! 	  hi_half[num] = simplify_gen_subreg (SImode, op, DImode, 4);
  	}
!     }
! }
! 
! /* Split one or more TImode RTL references into pairs of SImode
!    references.  The RTL can be REG, offsettable MEM, integer constant, or
!    CONST_DOUBLE.  "operands" is a pointer to an array of DImode RTL to
!    split and "num" is its length.  lo_half and hi_half are output arrays
!    that parallel "operands".  */
! 
! static void
! split_ti (operands, num, lo_half, hi_half)
!      rtx operands[];
!      int num;
!      rtx lo_half[], hi_half[];
! {
!   if (!TARGET_64BIT)
!     abort ();
!   while (num--)
!     {
!       rtx op = operands[num];
!       /* simplify_subreg refuse to simplify subregs around
! 	 volatile memory accesses, but on i386 we need it.  */
!       if (GET_CODE (op) == MEM)
  	{
  	  lo_half[num] = adjust_address (op, SImode, 0);
! 	  hi_half[num] = adjust_address (op, SImode, 8);
  	}
        else
! 	{
! 	  lo_half[num] = simplify_gen_subreg (DImode, op, DImode, 0);
! 	  hi_half[num] = simplify_gen_subreg (DImode, op, DImode, 8);
! 	}
      }
  }
+ 
  
  /* Output code to perform a 387 binary operation in INSN, one of PLUS,
     MINUS, MULT or DIV.  OPERANDS are the insn operands, where operands[3]
*************** ix86_split_to_parts (operand, parts, mod
*** 8482,8488 ****
      }
    else
      {
!       if (mode == XFmode || mode == TFmode)
  	{
  	  if (REG_P (operand))
  	    {
--- 8532,8540 ----
      }
    else
      {
!       if (mode == TImode)
! 	split_ti (&operand, 1, &parts[0], &parts[1]);
!       else if (mode == XFmode || mode == TFmode)
  	{
  	  if (REG_P (operand))
  	    {
*************** ix86_split_to_parts (operand, parts, mod
*** 8506,8514 ****
  	      REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, l);
  	      /* Do not use shift by 32 to avoid warning on 32bit systems.  */
  	      if (HOST_BITS_PER_WIDE_INT >= 64)
! 	        parts[0] = GEN_INT (l[0] + ((l[1] << 31) << 1));
  	      else
! 	        parts[0] = immed_double_const (l[0], l[1], DImode);
  	      parts[1] = GEN_INT (l[2]);
  	    }
  	  else
--- 8558,8566 ----
  	      REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, l);
  	      /* Do not use shift by 32 to avoid warning on 32bit systems.  */
  	      if (HOST_BITS_PER_WIDE_INT >= 64)
! 	        parts[0] = GEN_INT (l[1] + (((HOST_WIDE_INT)l[0] << 31) << 1));
  	      else
! 	        parts[0] = immed_double_const (l[1], l[0], DImode);
  	      parts[1] = GEN_INT (l[2]);
  	    }
  	  else
Index: config/i386/i386.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.h,v
retrieving revision 1.207
diff -c -3 -p -r1.207 i386.h
*** i386.h	2001/10/02 10:59:39	1.207
--- i386.h	2001/10/04 12:14:58
*************** extern int ix86_arch;
*** 953,959 ****
      ((mode) == QImode || (mode) == HImode || (mode) == SImode	\
       || (mode) == DImode					\
       || (mode) == CQImode || (mode) == CHImode || (mode) == CSImode \
!      || (mode) == CDImode)
  
  /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.  */
  
--- 955,962 ----
      ((mode) == QImode || (mode) == HImode || (mode) == SImode	\
       || (mode) == DImode					\
       || (mode) == CQImode || (mode) == CHImode || (mode) == CSImode \
!      || (mode) == CDImode					\
!      || (TARGET_64BIT && ((mode) == TImode || (mode) == CTImode)))
  
  /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.  */
  
Index: config/i386/i386.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.md,v
retrieving revision 1.298
diff -c -3 -p -r1.298 i386.md
*** i386.md	2001/10/02 10:59:39	1.298
--- i386.md	2001/10/04 12:15:02
***************
*** 17496,17501 ****
--- 17503,17513 ----
  	(match_operand:TI 1 "general_operand" ""))]
    "TARGET_SSE"
  {
+   if (TARGET_64BIT)
+     {
+       ix86_expand_move (TImode, operands);
+       DONE;
+     }
    /* For constants other than zero into memory.  We do not know how the
       instructions used to build constants modify the upper 64 bits
       of the register, once we have that information we may be able
***************
*** 17791,17801 ****
  (define_insn "movti_internal"
    [(set (match_operand:TI 0 "nonimmediate_operand" "=x,m")
  	(match_operand:TI 1 "general_operand" "xm,x"))]
!   "TARGET_SSE"
    "@
     movaps\t{%1, %0|%0, %1}
     movaps\t{%1, %0|%0, %1}"
    [(set_attr "type" "sse")])
  
  ;; These two patterns are useful for specifying exactly whether to use
  ;; movaps or movups
--- 17803,17835 ----
  (define_insn "movti_internal"
    [(set (match_operand:TI 0 "nonimmediate_operand" "=x,m")
  	(match_operand:TI 1 "general_operand" "xm,x"))]
!   "!TARGET_64BIT && TARGET_SSE"
    "@
     movaps\t{%1, %0|%0, %1}
     movaps\t{%1, %0|%0, %1}"
    [(set_attr "type" "sse")])
+ 
+ (define_insn "*movti_rex64"
+   [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o,mx,x")
+ 	(match_operand:TI 1 "general_operand" "riFo,riF,x,m"))]
+   "TARGET_64BIT
+    && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+   "@
+    #
+    #
+    movaps\\t{%1, %0|%0, %1}
+    movaps\\t{%1, %0|%0, %1}"
+   [(set_attr "type" "*,*,sse,sse")
+    (set_attr "mode" "TI")])
+ 
+ (define_split
+   [(set (match_operand:TI 0 "nonimmediate_operand" "")
+         (match_operand:TI 1 "general_operand" ""))]
+   "reload_completed
+    && (!MMX_REG_P (operands[0]) && !SSE_REG_P (operands[0]))
+    && (!MMX_REG_P (operands[1]) && !SSE_REG_P (operands[1]))"
+   [(const_int 0)]
+   "ix86_split_long_move (operands); DONE;")
  
  ;; These two patterns are useful for specifying exactly whether to use
  ;; movaps or movups


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