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] 2nd try: Add sseregparm function attribute for x86


I tried to address all concerns.

Bootstrapped and regtested on i686-pc-linux-gnu.

Ok for mainline?

Thanks,
Richard.
2005-06-08  Richard Guenther  <rguenth@gcc.gnu.org>

	* config/i386/i386.c: Add new target attribute sseregparm.
	(ix86_handle_sseregparm_attribute): New function.
	(ix86_function_sseregparm): New function, split out from ...
	(init_cumulative_args): ... here.  Use to decide use
	of SSE registers.
	(ix86_value_regno): Likewise.
	* doc/extend.texi: Document sseregparm target attribute.

	* gcc.dg/i386-sseregparm-1.c: New testcase.
	* gcc.dg/i386-sseregparm-2.c: Likewise.


Index: config/i386/i386.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.c,v
retrieving revision 1.826
diff -c -3 -p -r1.826 i386.c
*** config/i386/i386.c	8 Jun 2005 05:05:18 -0000	1.826
--- config/i386/i386.c	8 Jun 2005 20:39:29 -0000
*************** const struct attribute_spec ix86_attribu
*** 892,897 ****
--- 892,898 ----
  static bool ix86_function_ok_for_sibcall (tree, tree);
  static tree ix86_handle_cdecl_attribute (tree *, tree, tree, int, bool *);
  static tree ix86_handle_regparm_attribute (tree *, tree, tree, int, bool *);
+ static tree ix86_handle_sseregparm_attribute (tree *, tree, tree, int, bool *);
  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);
*************** const struct attribute_spec ix86_attribu
*** 1659,1664 ****
--- 1660,1668 ----
    /* Regparm attribute specifies how many integer arguments are to be
       passed in registers.  */
    { "regparm",   1, 1, false, true,  true,  ix86_handle_regparm_attribute },
+   /* Sseregparm attribute says we are using x86_64 calling conventions
+      for FP arguments.  */
+   { "sseregparm", 0, 0, false, true, true, ix86_handle_sseregparm_attribute },
  #if TARGET_DLLIMPORT_DECL_ATTRIBUTES
    { "dllimport", 0, 0, false, false, false, handle_dll_attribute },
    { "dllexport", 0, 0, false, false, false, handle_dll_attribute },
*************** ix86_handle_regparm_attribute (tree *nod
*** 1824,1829 ****
--- 1828,1852 ----
    return NULL_TREE;
  }
  
+ /* Handle a "sseregparm" attribute;
+    arguments as in struct attribute_spec.handler.  */
+ static tree
+ ix86_handle_sseregparm_attribute (tree *node, tree name,
+ 				 tree args ATTRIBUTE_UNUSED,
+ 				 int flags ATTRIBUTE_UNUSED,
+ 				 bool *no_add_attrs)
+ {
+   if (TREE_CODE (*node) != FUNCTION_TYPE
+       && TREE_CODE (*node) != METHOD_TYPE)
+     {
+       warning (OPT_Wattributes, "%qs attribute only applies to functions",
+ 	       IDENTIFIER_POINTER (name));
+       *no_add_attrs = true;
+     }
+ 
+   return NULL_TREE;
+ }
+ 
  /* Return 0 if the attributes for two types are incompatible, 1 if they
     are compatible, and 2 if they are nearly compatible (which causes a
     warning to be generated).  */
*************** ix86_function_regparm (tree type, tree d
*** 1897,1902 ****
--- 1920,1983 ----
    return regparm;
  }
  
+ /* Return true, if we can pass up to 8 SFmode and DFmode arguments
+    in SSE registers for a function with the indicated TYPE and DECL.
+    DECL may be NULL when calling function indirectly
+    or considering a libcall.  */
+ 
+ static bool
+ ix86_function_sseregparm (tree type, tree decl)
+ {
+   /* Use SSE registers to pass SFmode and DFmode arguments if requested
+      by the sseregparm attribute.  */
+   if (type
+       && lookup_attribute ("sseregparm", TYPE_ATTRIBUTES (type)))
+     {
+       tree argt;
+       bool use_sfmode = false, use_dfmode = false;
+ 
+       /* First look if we use SFmode or DFmode at all.  */
+       if (TYPE_MODE (TREE_TYPE (type)) == SFmode)
+         use_sfmode = true;
+       else if (TYPE_MODE (TREE_TYPE (type)) == DFmode)
+         use_dfmode = true;
+       for (argt = TYPE_ARG_TYPES (type); argt; argt = TREE_CHAIN (argt))
+         {
+ 	  if (TYPE_MODE (TREE_VALUE (argt)) == SFmode)
+ 	    use_sfmode = true;
+ 	  else if (TYPE_MODE (TREE_VALUE (argt)) == DFmode)
+ 	    use_dfmode = true;
+ 	}
+ 
+       if ((use_sfmode && !TARGET_SSE)
+ 	  || (use_dfmode && !TARGET_SSE2))
+         {
+ 	  if (decl)
+ 	    error ("Calling %qD with attribute sseregparm without "
+ 		   "SSE/SSE2 enabled", decl);
+ 	  else
+ 	    error ("Calling %qT with attribute sseregparm without "
+ 		   "SSE/SSE2 enabled", type);
+ 	  return false;
+ 	}
+ 
+       return true;
+     }
+ 
+   /* For local functions, pass SFmode (and DFmode for SSE2) arguments
+      in SSE registers even for 32-bit mode and not just 3, but up to
+      8 SSE arguments in registers.  */
+   if (!TARGET_64BIT && decl
+       && TARGET_SSE_MATH && flag_unit_at_a_time && !profile_flag)
+     {
+       struct cgraph_local_info *i = cgraph_local_info (decl);
+       if (i && i->local)
+ 	return true;
+     }
+ 
+   return false;
+ }
+ 
  /* Return true if EAX is live at the start of the function.  Used by
     ix86_expand_prologue to determine if we need special help before
     calling allocate_stack_worker.  */
*************** init_cumulative_args (CUMULATIVE_ARGS *c
*** 2083,2101 ****
        || (fntype && !TYPE_ARG_TYPES (fntype)))
      cum->maybe_vaarg = true;
  
!   /* For local functions, pass SFmode (and DFmode for SSE2) arguments
!      in SSE registers even for 32-bit mode and not just 3, but up to
!      8 SSE arguments in registers.  */
!   if (!TARGET_64BIT && !cum->maybe_vaarg && !cum->fastcall
!       && cum->sse_nregs == SSE_REGPARM_MAX && fndecl
!       && TARGET_SSE_MATH && flag_unit_at_a_time && !profile_flag)
      {
!       struct cgraph_local_info *i = cgraph_local_info (fndecl);
!       if (i && i->local)
! 	{
! 	  cum->sse_nregs = 8;
! 	  cum->float_in_sse = true;
! 	}
      }
  
    if (TARGET_DEBUG_ARG)
--- 2164,2176 ----
        || (fntype && !TYPE_ARG_TYPES (fntype)))
      cum->maybe_vaarg = true;
  
!   /* Set up the number of SSE registers used for passing SFmode
!      and DFmode arguments.  Warn for mismatching ABI.  */
!   if (!cum->maybe_vaarg && !cum->fastcall
!       && ix86_function_sseregparm (fntype, fndecl))
      {
!       cum->sse_nregs = 8;
!       cum->float_in_sse = true;
      }
  
    if (TARGET_DEBUG_ARG)
*************** ix86_value_regno (enum machine_mode mode
*** 3244,3257 ****
      return 0;
  
    /* Floating point return values in %st(0), except for local functions when
!      SSE math is enabled.  */
!   if (func && SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH
!       && flag_unit_at_a_time)
!     {
!       struct cgraph_local_info *i = cgraph_local_info (func);
!       if (i && i->local)
! 	return FIRST_SSE_REG;
!     }
  
    return FIRST_FLOAT_REG;
  }
--- 3320,3329 ----
      return 0;
  
    /* Floating point return values in %st(0), except for local functions when
!      SSE math is enabled or for functions with sseregparm attribute.  */
!   if (func && SSE_FLOAT_MODE_P (mode)
!       && ix86_function_sseregparm (TREE_TYPE (func), func))
!     return FIRST_SSE_REG;
  
    return FIRST_FLOAT_REG;
  }

Index: doc/extend.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/extend.texi,v
retrieving revision 1.254
diff -c -3 -p -r1.254 extend.texi
*** doc/extend.texi	30 May 2005 20:15:46 -0000	1.254
--- doc/extend.texi	8 Jun 2005 10:50:00 -0000
*************** safe since the loaders there save all re
*** 2141,2146 ****
--- 2149,2167 ----
  disabled with the linker or the loader if desired, to avoid the
  problem.)
  
+ @item sseregparm
+ @cindex @code{sseregparm} attribute
+ On the Intel 386 with SSE support, the @code{sseregparm} attribute
+ causes the compiler to pass up to 8 floating point arguments in
+ SSE registers instead of on the FP stack.  Functions that take a
+ variable number of arguments or marked with the @code{fastcall}
+ attribute will continue to be passed all of their FP arguments on the
+ FP stack.
+ 
+ Beware that calling external functions with SSE calling conventions
+ and without SSE support enabled with @code{-msse} will invoke
+ undefined behavior at runtime.
+ 
  @item returns_twice
  @cindex @code{returns_twice} attribute
  The @code{returns_twice} attribute tells the compiler that a function may


/*  { dg-do compile { target i?86-*-* x86_64-*-* } } */
/*  { dg-options "-O2 -msse2" } */

float essef(float) __attribute__((sseregparm));
double essed(double) __attribute__((sseregparm));
float ssef(float) __attribute__((sseregparm, noinline));
double ssed(double) __attribute__((sseregparm, noinline));
float ssef(float f) { return f; }
double ssed(double d) { return d; }
extern double d;
extern float f;
void test(void)
{
  f = essef(f);
  d = essed(d);
  f = ssef(f);
  d = ssed(d);
}

/* { dg-final { scan-assembler-not "fldl" } } */


/*  { dg-do compile { target i?86-*-* } } */
/*  { dg-options "-mno-sse" } */

float essef(float) __attribute__((sseregparm));
double essed(double) __attribute__((sseregparm));
float ssef(float) __attribute__((sseregparm, noinline));
double ssed(double) __attribute__((sseregparm, noinline));
float ssef(float f) { return f; } /* { dg-warning "SSE" } */
double ssed(double d) { return d; } /* { dg-warning "SSE" } */
extern double d;
extern float f;
void test(void)
{
  f = essef(f); /* { dg-warning "SSE" } */
  d = essed(d); /* { dg-warning "SSE" } */
  f = ssef(f); /* { dg-warning "SSE" } */
  d = ssed(d); /* { dg-warning "SSE" } */
}

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