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]

[PATCH, i386] Optionally use %xmm0 to return float and/or doublevalues


The attached patch implements the idea of returning floating point values in SSE registers. This is done as long as the ISA supports it (e.g. for floats on SSE processors, or for doubles on SSE2):

1) with the new -mfp-ret-in-sse option, for all functions

2) with -mfpmath=sse, for local functions

3) without any option, for functions that have the sse_return attribute.

Given the advanced state of development of 4.0.0, I have included a few asserts. Also, the code will not trigger unless the specific command-line options -mfpmath=sse or -mfp-ret-in-sse are included. It does not apply to x86-64 platforms, for which -mfpmath=sse is the default, because their ABI implementation is completely separate.

There are 9 new testcases:
- 2 compilation tests for -mfp-ret-in-sse (-msse, -msse2)
- 2 compilation tests for static functions (-msse, -msse2)
- 2 run-time tests for -mfp-ret-in-sse (-msse, -msse2)
- 3 compilation tests for sse_return (-msse, -msse2, no option) testing also warnings for inappropriate use of sse_return.


Here are some examples, taken from the new testcases:

1) Options used: -msse -mfp-ret-in-sse -mfpmath=sse:

   float x() { return 3.14159265; }
   float y(float a) { return a * x(); }

   x:
        movss   .LC0, %xmm0
        ret
   y:
        call    x
        mulss   4(%esp), %xmm0
        ret

2) -msse2 -mfp-ret-in-sse -mfpmath=sse:

   double x() { return 3.14159265; }
   double y(float a) { return a * x(); }

   x:
        movsd   .LC0, %xmm0
        ret
   y:
        call    x
        mulsd   4(%esp), %xmm0
        ret

3) -msse2 -mfpmath=sse -O2 -fomit-frame-pointer -fno-inline
   (and the standard -mfp-ret-in-i387)

   static double x() { return 3.14159265; }
   double y(double a) { return a * x(); }

   x:
        movsd   .LC0, %xmm0
        ret
   y:
        subl    $12, %esp
        fldl    16(%esp)
        fstpl   (%esp)
        call    x
        mulsd   (%esp), %xmm0
        movsd   %xmm0, (%esp)
        fldl    (%esp)
        addl    $12, %esp
        ret

   where the global function is still using the %st0-based calling
   convention.

Booted i686-pc-linux-gnu (P4), all languages except Ada,
tests in progress (gcc directory already done).

Ok for mainline?

Paolo
gcc:
2005-01-25  Paolo Bonzini  <bonzini@gnu.org>

	* config/i386/i386-protos.h (ix86_function_value): Accept two
	arguments, like the target macro.
	* config/i386/i386.h (TARGET_FLOAT_RETURNS_IN_SSE,
	MASK_SSE_FLOAT_RETURNS): New.
	(FUNCTION_VALUE): Pass both arguments.
	(TARGET_SWITCHES): Add -mfp-ret-in-sse, -mno-fp-ret-in-sse.
	* config/i386/i386.c (ix86_handle_sse_return_attribute): New.
	(ix86_function_value): Accept the second argument of the target macro.
	(override_options): Process -mfp-ret-in-sse.
	(ix86_function_ok_for_sibcall): Pass a function pointer to
	ix86_function_value.
	(ix86_function_value_regno_p): Simplify and support -mfp-ret-in-sse.
	(ix86_function_value, ix86_libcall_value) [!TARGET_64BIT]: Adjust
	call to ix86_value_regno).
	(ix86_value_regno): Add support for returning parameters in SSE
	registers.

	* doc/extend.texi (Function attributes): Document sse_return.
	* doc/invoke.texi (i386 options): Document -mfp-ret-in-sse and its
	interaction with -mfp-ret-in-i387.

gcc/testsuite:
2005-01-25  Paolo Bonzini  <bonzini@gnu.org>

	* gcc.dg/i386-ssefn-1.c, gcc.dg/i386-ssefn-2.c, gcc.dg/i386-ssefn-3.c,
	gcc.dg/i386-ssefn-4.c, gcc.dg/i386-ssefn-5.c, gcc.dg/i386-ssefn-6.c,
	gcc.dg/i386-ssefn-7.c, gcc.dg/i386-ssefn-8.c, gcc.dg/i386-ssefn-9.c:
	New.

Index: config/i386/i386-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386-protos.h,v
retrieving revision 1.128
diff -u -p -r1.128 i386-protos.h
--- config/i386/i386-protos.h	20 Jan 2005 18:20:42 -0000	1.128
+++ config/i386/i386-protos.h	25 Jan 2005 14:17:21 -0000
@@ -199,7 +199,7 @@ extern void init_cumulative_args (CUMULA
 extern rtx function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
 extern void function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
 				  tree, int);
-extern rtx ix86_function_value (tree);
+extern rtx ix86_function_value (tree, tree);
 #endif
 
 #endif
Index: config/i386/i386.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.c,v
retrieving revision 1.789
diff -u -p -r1.789 i386.c
--- config/i386/i386.c	22 Jan 2005 23:07:53 -0000	1.789
+++ config/i386/i386.c	25 Jan 2005 14:17:23 -0000
@@ -908,8 +908,9 @@ static int ix86_function_regparm (tree, 
 const struct attribute_spec ix86_attribute_table[];
 static bool ix86_function_ok_for_sibcall (tree, tree);
 static tree ix86_handle_cdecl_attribute (tree *, tree, tree, int, bool *);
+static tree ix86_handle_sse_return_attribute (tree *, tree, tree, int, bool *);
 static tree ix86_handle_regparm_attribute (tree *, tree, tree, int, bool *);
-static int ix86_value_regno (enum machine_mode);
+static int ix86_value_regno (enum machine_mode, tree);
 static bool contains_128bit_aligned_vector_p (tree);
 static rtx ix86_struct_value_rtx (tree, int);
 static bool ix86_ms_bitfield_layout_p (tree);
@@ -1561,6 +1562,15 @@ override_options (void)
   if (!TARGET_80387)
     target_flags &= ~MASK_FLOAT_RETURNS;
 
+  /* Likewise for SSE. */
+  if (!TARGET_SSE)
+    target_flags &= ~MASK_SSE_FLOAT_RETURNS;
+
+  /* Between SSE and 80387 return registers, prefer SSE (since it is not
+     the default).  */
+  if (TARGET_FLOAT_RETURNS_IN_SSE)
+    target_flags &= ~MASK_FLOAT_RETURNS;
+
   if ((x86_accumulate_outgoing_args & TUNEMASK)
       && !(target_flags_explicit & MASK_ACCUMULATE_OUTGOING_ARGS)
       && !optimize_size)
@@ -1616,6 +1626,9 @@ const struct attribute_spec ix86_attribu
   { "fastcall",  0, 0, false, true,  true,  ix86_handle_cdecl_attribute },
   /* Cdecl attribute says the callee is a normal C declaration */
   { "cdecl",     0, 0, false, true,  true,  ix86_handle_cdecl_attribute },
+  /* sse_return says the callee will return float and double values in
+     %xmm0, respectively if SSE or SSE2 are enabled.  */
+  { "sse_return", 0, 0, false, true,  true,  ix86_handle_sse_return_attribute },
   /* Regparm attribute specifies how many integer arguments are to be
      passed in registers.  */
   { "regparm",   1, 1, false, true,  true,  ix86_handle_regparm_attribute },
@@ -1639,19 +1652,33 @@ const struct attribute_spec ix86_attribu
 static bool
 ix86_function_ok_for_sibcall (tree decl, tree exp)
 {
+  tree func;
+
   /* If we are generating position-independent code, we cannot sibcall
      optimize any indirect call, or a direct call to a global function,
      as the PLT requires %ebx be live.  */
   if (!TARGET_64BIT && flag_pic && (!decl || TREE_PUBLIC (decl)))
     return false;
 
+  if (decl)
+    func = decl;
+  else
+    {
+      /* We're looking at the CALL_EXPR, we need the type of the function.  */
+      func = TREE_OPERAND (exp, 0);		/* pointer expression */
+      func = TREE_TYPE (func);			/* pointer type */
+
+      /* TREE_TYPE (func) is a function type.  */
+    }
+
   /* If we are returning floats on the 80387 register stack, we cannot
      make a sibcall from a function that doesn't return a float to a
      function that does or, conversely, from a function that does return
      a float to a function that doesn't; the necessary stack adjustment
      would not be executed.  */
-  if (STACK_REG_P (ix86_function_value (TREE_TYPE (exp)))
-      != STACK_REG_P (ix86_function_value (TREE_TYPE (DECL_RESULT (cfun->decl)))))
+  if (STACK_REG_P (ix86_function_value (TREE_TYPE (exp), func))
+      != STACK_REG_P (ix86_function_value (TREE_TYPE (DECL_RESULT (cfun->decl)),
+					   TREE_TYPE (cfun->decl))))
     return false;
 
   /* If this call is indirect, we'll need to be able to use a call-clobbered
@@ -1659,12 +1686,7 @@ ix86_function_ok_for_sibcall (tree decl,
      such registers are not used for passing parameters.  */
   if (!decl && !TARGET_64BIT)
     {
-      tree type;
-
-      /* We're looking at the CALL_EXPR, we need the type of the function.  */
-      type = TREE_OPERAND (exp, 0);		/* pointer expression */
-      type = TREE_TYPE (type);			/* pointer type */
-      type = TREE_TYPE (type);			/* function type */
+      tree type = TREE_TYPE (func);
 
       if (ix86_function_regparm (type, NULL) >= 3)
 	{
@@ -1725,6 +1747,63 @@ ix86_handle_cdecl_attribute (tree *node,
   return NULL_TREE;
 }
 
+/* Handle a "sse_return" attribute;
+   arguments as in struct attribute_spec.handler.  */
+static tree
+ix86_handle_sse_return_attribute (tree *node, tree name,
+			          tree args ATTRIBUTE_UNUSED,
+			          int flags ATTRIBUTE_UNUSED,
+				  bool *no_add_attrs)
+{
+  tree *type = NULL;
+  if (DECL_P (*node))
+    {
+      if (TREE_CODE (*node) == TYPE_DECL
+	  || TREE_CODE (*node) == FIELD_DECL)
+	type = &TREE_TYPE (*node);
+    }
+  else
+    type = node;
+
+  if (TREE_CODE (*type) != FUNCTION_TYPE
+      && TREE_CODE (*type) != METHOD_TYPE)
+    {
+      warning ("%qs attribute only applies to functions",
+	       IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
+    }
+  else
+    {
+      enum machine_mode mode = TYPE_MODE (TREE_TYPE (*type));
+
+      if (TARGET_64BIT)
+        {
+          warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
+          *no_add_attrs = true;
+        }
+      else if (mode == DFmode && !TARGET_SSE2)
+	{
+	  warning ("%qs attribute ignored for doubles "
+		   "on non-SSE2 targets", IDENTIFIER_POINTER (name));
+          *no_add_attrs = true;
+        }
+      else if (mode == SFmode && !TARGET_SSE)
+	{
+	  warning ("%qs attribute ignored on non-SSE targets",
+		   IDENTIFIER_POINTER (name));
+          *no_add_attrs = true;
+        }
+      else if (mode != SFmode && mode != DFmode)
+	{
+	  warning ("%qs attribute ignored for a %qT return value",
+		   IDENTIFIER_POINTER (name), TREE_TYPE (*type));
+          *no_add_attrs = true;
+        }
+    }
+
+  return NULL_TREE;
+}
+
 /* Handle a "regparm" attribute;
    arguments as in struct attribute_spec.handler.  */
 static tree
@@ -3011,15 +3091,11 @@ ix86_function_arg_boundary (enum machine
 bool
 ix86_function_value_regno_p (int regno)
 {
-  if (!TARGET_64BIT)
-    {
-      return ((regno) == 0
-	      || ((regno) == FIRST_FLOAT_REG && TARGET_FLOAT_RETURNS_IN_80387)
-	      || ((regno) == FIRST_SSE_REG && TARGET_SSE));
-    }
-  return ((regno) == 0 || (regno) == FIRST_FLOAT_REG
-	  || ((regno) == FIRST_SSE_REG && TARGET_SSE)
-	  || ((regno) == FIRST_FLOAT_REG && TARGET_FLOAT_RETURNS_IN_80387));
+  return (regno == 0
+	  || (regno == FIRST_SSE_REG && TARGET_SSE)
+	  || (regno == FIRST_FLOAT_REG && (TARGET_64BIT
+					   || TARGET_FLOAT_RETURNS_IN_SSE
+					   || TARGET_FLOAT_RETURNS_IN_80387)));
 }
 
 /* Define how to find the value returned by a function.
@@ -3027,7 +3103,7 @@ ix86_function_value_regno_p (int regno)
    If the precise function being called is known, FUNC is its FUNCTION_DECL;
    otherwise, FUNC is 0.  */
 rtx
-ix86_function_value (tree valtype)
+ix86_function_value (tree valtype, tree func)
 {
   enum machine_mode natmode = type_natural_mode (valtype);
 
@@ -3043,7 +3119,7 @@ ix86_function_value (tree valtype)
       return ret;
     }
   else
-    return gen_rtx_REG (TYPE_MODE (valtype), ix86_value_regno (natmode));
+    return gen_rtx_REG (TYPE_MODE (valtype), ix86_value_regno (natmode, func));
 }
 
 /* Return false iff type is returned in memory.  */
@@ -3145,23 +3221,57 @@ ix86_libcall_value (enum machine_mode mo
 	}
     }
   else
-    return gen_rtx_REG (mode, ix86_value_regno (mode));
+    return gen_rtx_REG (mode, ix86_value_regno (mode, NULL));
 }
 
 /* Given a mode, return the register to use for a return value.  */
 
 static int
-ix86_value_regno (enum machine_mode mode)
+ix86_value_regno (enum machine_mode mode, tree func)
 {
-  /* Floating point return values in %st(0).  */
-  if (GET_MODE_CLASS (mode) == MODE_FLOAT && TARGET_FLOAT_RETURNS_IN_80387)
-    return FIRST_FLOAT_REG;
+  bool can_use_sse;
+  gcc_assert (!TARGET_64BIT);
+
   /* 16-byte vector modes in %xmm0.  See ix86_return_in_memory for where
      we prevent this case when sse is not available.  */
   if (mode == TImode || (VECTOR_MODE_P (mode) && GET_MODE_SIZE (mode) == 16))
     return FIRST_SSE_REG;
-  /* Everything else in %eax.  */
-  return 0;
+
+  /* Most things go in %eax, except (unless -mno-fp-ret-in-387) fp values.  */
+  if (GET_MODE_CLASS (mode) != MODE_FLOAT
+      || (!TARGET_FLOAT_RETURNS_IN_80387 && !TARGET_FLOAT_RETURNS_IN_SSE))
+    return 0;
+
+  gcc_assert (TARGET_FLOAT_RETURNS_IN_80387 || TARGET_FLOAT_RETURNS_IN_SSE);
+
+  /* Floating point return values in %st(0), but with several exceptions.  */
+  can_use_sse = (TARGET_SSE && mode == SFmode)
+		|| (TARGET_SSE2 && mode == DFmode);
+
+  /* Floating point return values in %xmm0 if specified on command-line.  */
+  if (TARGET_FLOAT_RETURNS_IN_SSE && can_use_sse)
+    return FIRST_SSE_REG;
+
+   /* Floating point return values in %xmm0 for local functions or if
+      specified with an attribute.  */
+  if (func)
+    {
+      bool has_attr = lookup_attribute ("sse_return",
+					TYPE_ATTRIBUTES (TREE_TYPE (func)))
+		      != NULL;
+
+      if (has_attr)
+	gcc_assert (can_use_sse);
+
+      if (can_use_sse)
+	{
+          struct cgraph_local_info *i = cgraph_local_info (func);
+          if (has_attr || (i && i->local && TARGET_SSE_MATH))
+	    return FIRST_SSE_REG;
+	}
+    }
+
+  return FIRST_FLOAT_REG;
 }
 
 /* Create the va_list data type.  */
Index: config/i386/i386.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.h,v
retrieving revision 1.419
diff -u -p -r1.419 i386.h
--- config/i386/i386.h	20 Jan 2005 06:47:25 -0000	1.419
+++ config/i386/i386.h	25 Jan 2005 14:17:24 -0000
@@ -128,8 +128,9 @@ extern int target_flags;
 #define MASK_64BIT		0x00100000	/* Produce 64bit code */
 #define MASK_MS_BITFIELD_LAYOUT 0x00200000	/* Use native (MS) bitfield layout */
 #define MASK_TLS_DIRECT_SEG_REFS 0x00400000	/* Avoid adding %gs:0  */
+#define MASK_SSE_FLOAT_RETURNS	0x00800000	/* Return float in %xmm0 */
 
-/* Unused:			0x03e0000	*/
+/* Unused:			0x0300000	*/
 
 /* ... overlap with subtarget options starts by 0x04000000.  */
 #define MASK_NO_RED_ZONE	0x04000000	/* Do not use red zone */
@@ -168,6 +169,12 @@ extern int target_flags;
    the 387 to be used, which is compatible with most calling conventions.  */
 #define TARGET_FLOAT_RETURNS_IN_80387 (target_flags & MASK_FLOAT_RETURNS)
 
+/* Functions that return a floating point value may return that value
+   in the 387 FPU or in SSE registers.  If reset, this flag causes
+   the SSE to be used, which is incompatible with most calling conventions
+   but ought to be faster.  */
+#define TARGET_FLOAT_RETURNS_IN_SSE (target_flags & MASK_SSE_FLOAT_RETURNS)
+
 /* Long double is 128bit instead of 96bit, even when only 80bits are used.
    This mode wastes cache, but avoid misaligned data accesses and simplifies
    address calculations.  */
@@ -363,6 +370,10 @@ extern int x86_prefetch_sse;
     N_("Return values of functions in FPU registers") },		      \
   { "no-fp-ret-in-387",		-MASK_FLOAT_RETURNS ,			      \
     N_("Do not return values of functions in FPU registers")},		      \
+  { "fp-ret-in-sse",		 MASK_SSE_FLOAT_RETURNS,		      \
+    N_("Return values of functions in SSE registers") },		      \
+  { "no-fp-ret-in-sse",		-MASK_SSE_FLOAT_RETURNS ,		      \
+    N_("Do not return values of functions in SSE registers")},		      \
   { "no-fancy-math-387",	 MASK_NO_FANCY_MATH_387,		      \
     N_("Do not generate sin, cos, sqrt for FPU") },			      \
   { "fancy-math-387",		-MASK_NO_FANCY_MATH_387,		      \
@@ -1705,7 +1716,7 @@ enum reg_class
    If the precise function being called is known, FUNC is its FUNCTION_DECL;
    otherwise, FUNC is 0.  */
 #define FUNCTION_VALUE(VALTYPE, FUNC)  \
-   ix86_function_value (VALTYPE)
+   ix86_function_value (VALTYPE, FUNC)
 
 #define FUNCTION_VALUE_REGNO_P(N) \
   ix86_function_value_regno_p (N)
Index: doc/extend.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/extend.texi,v
retrieving revision 1.235
diff -u -r1.235 extend.texi
--- doc/extend.texi	3 Dec 2004 17:37:09 -0000	1.235
+++ doc/extend.texi	25 Jan 2005 14:05:25 -0000
@@ -2165,6 +2165,19 @@
                           sp_switch ("alt_stack")));
 @end smallexample
 
+@item sse_return
+@cindex @code{sse_return} attribute
+@cindex functions with return values in SSE registers on the 386
+The Intel 32-bit ABI specifies that values of types @code{float}
+and @code{double} are returned in an FPU register, but this is not
+the best choice for programs using SSE.
+
+This attribute causes such values to be returned in SSE
+registers instead.  It does not affect return values of types
+@code{long double}, which are always returned in FPU registers.
+This attribute will only be honored when compiling for a machine
+that uses SSE for math (for example, with @option{-mfpmath=sse}).
+
 @item stdcall
 @cindex functions that pop the argument stack on the 386
 On the Intel 386, the @code{stdcall} attribute causes the compiler to
Index: doc/invoke.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/invoke.texi,v
retrieving revision 1.569
diff -u -r1.569 invoke.texi
--- doc/invoke.texi	19 Jan 2005 09:31:09 -0000	1.569
+++ doc/invoke.texi	25 Jan 2005 14:05:27 -0000
@@ -485,7 +485,7 @@
 @gccoptlist{-mtune=@var{cpu-type}  -march=@var{cpu-type} @gol
 -mfpmath=@var{unit} @gol
 -masm=@var{dialect}  -mno-fancy-math-387 @gol
--mno-fp-ret-in-387  -msoft-float  -msvr3-shlib @gol
+-mno-fp-ret-in-387  -mfp-ret-in-sse  -msoft-float  -msvr3-shlib @gol
 -mno-wide-multiply  -mrtd  -malign-double @gol
 -mpreferred-stack-boundary=@var{num} @gol
 -mmmx  -msse  -msse2 -msse3 -m3dnow @gol
@@ -8500,6 +8500,29 @@
 The option @option{-mno-fp-ret-in-387} causes such values to be returned
 in ordinary CPU registers instead.
 
+Specifying this option together with @option{-mfp-ret-in-sse} does not
+make much sense, because @option{-mfp-ret-in-sse} does use FPU registers
+to return @code{long double} values.  In case you do specify both of these
+options, @option{-mfp-ret-in-sse} takes precedence.
+
+@item -mfp-ret-in-sse
+@opindex mfp-ret-in-sse
+Use the SSE registers for return values of functions.
+
+The usual calling convention has functions return values of types
+@code{float} and @code{double} in an FPU register, but this is not
+the best choice for programs using SSE.
+
+The option @option{-mfp-ret-in-sse} causes such values to be returned
+in SSE registers instead.  It does not affect return values of
+types @code{long double}, which are always returned in FPU registers
+@emph{even if @code{-mno-fp-ret-in-387} is specified}.  You can control
+this behavior for a specific function by using the function attribute
+@samp{sse_return}.
+
+@strong{Warning:} if you use this switch, then you must build all modules
+with the same value, including any libraries and in particular @file{libm}.
+
 @item -mno-fancy-math-387
 @opindex mno-fancy-math-387
 Some 387 emulators do not support the @code{sin}, @code{cos} and
Index: testsuite/gcc.dg/i386-ssefn-1.c
===================================================================
RCS file: testsuite/gcc.dg/i386-ssefn-1.c
diff -N testsuite/gcc.dg/i386-ssefn-1.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/i386-ssefn-1.c	25 Jan 2005 14:05:21 -0000
@@ -0,0 +1,30 @@
+/* Test argument passing with SSE and -mfp-ret-in-sse
+   Written by Paolo Bonzini, 25 January 2005 */
+
+/* { dg-do compile { target i?86-*-* } } */
+/* { dg-final { scan-assembler "movss" } } */
+/* { dg-final { scan-assembler "mulss" } } */
+/* { dg-final { scan-assembler-not "movsd" } } */
+/* { dg-final { scan-assembler-not "mulsd" } } */
+/* { dg-options "-O2 -msse -mfpmath=sse -mfp-ret-in-sse" } */
+
+float xs (void)
+{
+  return 3.14159265;
+}
+
+float ys (float a)
+{
+  return xs () * a;
+}
+
+double xd (void)
+{
+  return 3.1415926535;
+}
+
+double yd (double a)
+{
+  return xd () * a;
+}
+
Index: testsuite/gcc.dg/i386-ssefn-2.c
===================================================================
RCS file: testsuite/gcc.dg/i386-ssefn-2.c
diff -N testsuite/gcc.dg/i386-ssefn-2.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/i386-ssefn-2.c	25 Jan 2005 14:05:21 -0000
@@ -0,0 +1,30 @@
+/* Test argument passing with SSE2 and -mfp-ret-in-sse
+   Written by Paolo Bonzini, 25 January 2005 */
+
+/* { dg-do compile { target i?86-*-* } } */
+/* { dg-final { scan-assembler "movss" } } */
+/* { dg-final { scan-assembler "mulss" } } */
+/* { dg-final { scan-assembler "movsd" } } */
+/* { dg-final { scan-assembler "mulsd" } } */
+/* { dg-options "-O2 -msse2 -mfpmath=sse -mfp-ret-in-sse" } */
+
+float xs (void)
+{
+  return 3.14159265;
+}
+
+float ys (float a)
+{
+  return xs () * a;
+}
+
+double xd (void)
+{
+  return 3.1415926535;
+}
+
+double yd (double a)
+{
+  return xd () * a;
+}
+
Index: testsuite/gcc.dg/i386-ssefn-3.c
===================================================================
RCS file: testsuite/gcc.dg/i386-ssefn-3.c
diff -N testsuite/gcc.dg/i386-ssefn-3.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/i386-ssefn-3.c	25 Jan 2005 14:05:21 -0000
@@ -0,0 +1,30 @@
+/* Test argument passing with SSE and local functions
+   Written by Paolo Bonzini, 25 January 2005 */
+
+/* { dg-do compile { target i?86-*-* } } */
+/* { dg-final { scan-assembler "movss" } } */
+/* { dg-final { scan-assembler "mulss" } } */
+/* { dg-final { scan-assembler-not "movsd" } } */
+/* { dg-final { scan-assembler-not "mulsd" } } */
+/* { dg-options "-O2 -msse -mfpmath=sse -fno-inline" } */
+
+static float xs (void)
+{
+  return 3.14159265;
+}
+
+float ys (float a)
+{
+  return xs () * a;
+}
+
+static double xd (void)
+{
+  return 3.1415926535;
+}
+
+double yd (double a)
+{
+  return xd () * a;
+}
+
Index: testsuite/gcc.dg/i386-ssefn-4.c
===================================================================
RCS file: testsuite/gcc.dg/i386-ssefn-4.c
diff -N testsuite/gcc.dg/i386-ssefn-4.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/i386-ssefn-4.c	25 Jan 2005 14:05:21 -0000
@@ -0,0 +1,30 @@
+/* Test argument passing with SSE2 and local functions
+   Written by Paolo Bonzini, 25 January 2005 */
+
+/* { dg-do compile { target i?86-*-* } } */
+/* { dg-final { scan-assembler "movss" } } */
+/* { dg-final { scan-assembler "mulss" } } */
+/* { dg-final { scan-assembler "movsd" } } */
+/* { dg-final { scan-assembler "mulsd" } } */
+/* { dg-options "-O2 -msse2 -mfpmath=sse -fno-inline" } */
+
+static float xs (void)
+{
+  return 3.14159265;
+}
+
+float ys (float a)
+{
+  return xs () * a;
+}
+
+static double xd (void)
+{
+  return 3.1415926535;
+}
+
+double yd (double a)
+{
+  return xd () * a;
+}
+
Index: testsuite/gcc.dg/i386-ssefn-5.c
===================================================================
RCS file: testsuite/gcc.dg/i386-ssefn-5.c
diff -N testsuite/gcc.dg/i386-ssefn-5.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/i386-ssefn-5.c	25 Jan 2005 14:05:21 -0000
@@ -0,0 +1,42 @@
+/* Execution test for argument passing with SSE and -mfp-ret-in-sse
+   Written by Paolo Bonzini, 25 January 2005 */
+
+/* { dg-do run { target i?86-*-* } } */
+/* { dg-options "-O2 -msse -mfpmath=sse -mfp-ret-in-sse" } */
+#include <assert.h>
+#include "i386-cpuid.h"
+
+float xs (void)
+{
+  return 3.14159265;
+}
+
+float ys (float a)
+{
+  return xs () * a;
+}
+
+double xd (void)
+{
+  return 3.1415926535;
+}
+
+double yd (double a)
+{
+  return xd () * a;
+}
+
+int main()
+{
+  unsigned long cpu_facilities;
+
+  cpu_facilities = i386_cpuid ();
+
+  if (cpu_facilities & bit_SSE)
+    {
+      assert (ys (1) == xs ());
+      assert (ys (2) == xs () * 2);
+      assert (yd (1) == xd ());
+      assert (yd (2) == xd () * 2);
+    }
+}
Index: testsuite/gcc.dg/i386-ssefn-6.c
===================================================================
RCS file: testsuite/gcc.dg/i386-ssefn-6.c
diff -N testsuite/gcc.dg/i386-ssefn-6.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/i386-ssefn-6.c	25 Jan 2005 14:05:21 -0000
@@ -0,0 +1,42 @@
+/* Execution test for argument passing with SSE2 and -mfp-ret-in-sse
+   Written by Paolo Bonzini, 25 January 2005 */
+
+/* { dg-do run { target i?86-*-* } } */
+/* { dg-options "-O2 -msse2 -mfpmath=sse -mfp-ret-in-sse" } */
+#include <assert.h>
+#include "i386-cpuid.h"
+
+float xs (void)
+{
+  return 3.14159265;
+}
+
+float ys (float a)
+{
+  return xs () * a;
+}
+
+double xd (void)
+{
+  return 3.1415926535;
+}
+
+double yd (double a)
+{
+  return xd () * a;
+}
+
+int main()
+{
+  unsigned long cpu_facilities;
+
+  cpu_facilities = i386_cpuid ();
+
+  if (cpu_facilities & bit_SSE2)
+    {
+      assert (ys (1) == xs ());
+      assert (ys (2) == xs () * 2);
+      assert (yd (1) == xd ());
+      assert (yd (2) == xd () * 2);
+    }
+}
Index: testsuite/gcc.dg/i386-ssefn-7.c
===================================================================
RCS file: testsuite/gcc.dg/i386-ssefn-7.c
diff -N testsuite/gcc.dg/i386-ssefn-7.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/i386-ssefn-7.c	25 Jan 2005 14:05:21 -0000
@@ -0,0 +1,40 @@
+/* Test for argument passing with SSE and __attribute__ ((sse_return))
+   Written by Paolo Bonzini, 25 January 2005 */
+
+/* { dg-do compile { target i?86-*-* } } */
+/* { dg-final { scan-assembler "movss" } } */
+/* { dg-final { scan-assembler "mulss" } } */
+/* { dg-final { scan-assembler-not "movsd" } } */
+/* { dg-final { scan-assembler-not "mulsd" } } */
+/* { dg-options "-O2 -msse -mfpmath=sse" } */
+
+__attribute__ ((sse_return)) float xs (void)
+{
+  return 3.14159265;
+}
+
+__attribute__ ((sse_return)) float ys (float a)
+{
+  return xs () * a;
+}
+
+__attribute__ ((sse_return)) double xd (void)
+{ /* { dg-warning "sse_return" } */
+  return 3.1415926535;
+}
+
+__attribute__ ((sse_return)) double yd (double a)
+{ /* { dg-warning "sse_return" } */
+  return xd () * a;
+}
+
+__attribute__ ((sse_return)) long double xld (void)
+{ /* { dg-warning "sse_return" } */
+  return 3.1415926535L;
+}
+
+__attribute__ ((sse_return)) long double yld (long double a)
+{ /* { dg-warning "sse_return" } */
+  return xld () * a;
+}
+
Index: testsuite/gcc.dg/i386-ssefn-8.c
===================================================================
RCS file: testsuite/gcc.dg/i386-ssefn-8.c
diff -N testsuite/gcc.dg/i386-ssefn-8.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/i386-ssefn-8.c	25 Jan 2005 14:05:21 -0000
@@ -0,0 +1,40 @@
+/* Test for argument passing with SSE2 and __attribute__ ((sse_return))
+   Written by Paolo Bonzini, 25 January 2005 */
+
+/* { dg-do compile { target i?86-*-* } } */
+/* { dg-final { scan-assembler "movss" } } */
+/* { dg-final { scan-assembler "mulss" } } */
+/* { dg-final { scan-assembler "movsd" } } */
+/* { dg-final { scan-assembler "mulsd" } } */
+/* { dg-options "-O2 -msse2 -mfpmath=sse" } */
+
+__attribute__ ((sse_return)) float xs (void)
+{
+  return 3.14159265;
+}
+
+__attribute__ ((sse_return)) float ys (float a)
+{
+  return xs () * a;
+}
+
+__attribute__ ((sse_return)) double xd (void)
+{
+  return 3.1415926535;
+}
+
+__attribute__ ((sse_return)) double yd (double a)
+{
+  return xd () * a;
+}
+
+__attribute__ ((sse_return)) long double xld (void)
+{ /* { dg-warning "sse_return" } */
+  return 3.1415926535L;
+}
+
+__attribute__ ((sse_return)) long double yld (long double a)
+{ /* { dg-warning "sse_return" } */
+  return xld () * a;
+}
+
Index: testsuite/gcc.dg/i386-ssefn-9.c
===================================================================
RCS file: testsuite/gcc.dg/i386-ssefn-9.c
diff -N testsuite/gcc.dg/i386-ssefn-9.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/i386-ssefn-9.c	25 Jan 2005 14:05:21 -0000
@@ -0,0 +1,40 @@
+/* Test for argument passing with no SSE and __attribute__ ((sse_return))
+   Written by Paolo Bonzini, 25 January 2005 */
+
+/* { dg-do compile { target i?86-*-* } } */
+/* { dg-final { scan-assembler-not "movss" } } */
+/* { dg-final { scan-assembler-not "mulss" } } */
+/* { dg-final { scan-assembler-not "movsd" } } */
+/* { dg-final { scan-assembler-not "mulsd" } } */
+/* { dg-options "-O2" } */
+
+__attribute__ ((sse_return)) float xs (void)
+{ /* { dg-warning "sse_return" } */
+  return 3.14159265;
+}
+
+__attribute__ ((sse_return)) float ys (float a)
+{ /* { dg-warning "sse_return" } */
+  return xs () * a;
+}
+
+__attribute__ ((sse_return)) double xd (void)
+{ /* { dg-warning "sse_return" } */
+  return 3.1415926535;
+}
+
+__attribute__ ((sse_return)) double yd (double a)
+{ /* { dg-warning "sse_return" } */
+  return xd () * a;
+}
+
+__attribute__ ((sse_return)) long double xld (void)
+{ /* { dg-warning "sse_return" } */
+  return 3.1415926535L;
+}
+
+__attribute__ ((sse_return)) long double yld (long double a)
+{ /* { dg-warning "sse_return" } */
+  return xld () * a;
+}
+

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