This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[RFC] Drop in for toplevel libsse2
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 1 Aug 2005 17:36:36 +0200 (CEST)
- Subject: [RFC] Drop in for toplevel libsse2
This is a drop in patch & tarball (re-generate configure and
toplevel Makefile.in yourself) to provide gcc with an SSE2 ABI
math library and make it emit calls to it if sse math is in effect
and you did specify the -msselibm parameter.
People suggested a different name (libgccm or similar) and sub-directories
inside the lib to allow for other targets to drop functions there.
I guess this would be a good place for the vectorized sin/cos intrinsics,
too.
Note that the libsse2 code is a 1-to-1 copy of what is currently in the
libc/sysdeps/ieee754 dbl-64 and flt-32 subdirectories with some glue
magic to get an SSE2 ABI.
I'd like to have both general suggestions (change name to libgccm,
make subdirectories, do other stuff) and "whee - these ugly C routines
from libc never will go into toplevel, please write asm routines",
to give me a hint how hard I should push the current state for 4.1.
You can get the new toplevel lib as a tarball from
http://www.tat.physik.uni-tuebingen.de/~rguenth/gcc/libsse2-drop-in-2.tgz
Thanks,
Richard.
2005-08-01 Richard Guenther <rguenther@suse.de>
* Makefile.def (target_modules): Add libsse2.
* configure.in (target_libraries): Add libsse2.
(--(enable|disable)-libsse2): New configure switch.
* Makefine.in: Rebuilt.
* configure: Rebuilt.
* gcc.c (LINK_SSE2_SPEC): Define.
(link_sse2_spec): New variable.
(LINK_COMMAND_SPEC): Add %(link_sse2).
(static_specs): Add link_sse2_spec.
* config/i386/i386.h (LINK_SSE2_SPEC): Define.
* c-common.c (def_builtin_1): Store implicit decl in
implicit_built_in_decls array.
* call.c (build_call): Remove assert.
* config/i386/i386.c (ix86_init_builtins): With SSE2
support and fpmath=sse change (some) builtin math
functions to be sseregparm and redirect their assembler_name
to an appropriate library routine.
* config/i386/i386.opt (msselibm): New option.
* doc/invoke.texi: Document -msselibm.
Index: Makefile.def
===================================================================
RCS file: /cvs/gcc/gcc/Makefile.def,v
retrieving revision 1.56
diff -c -3 -p -r1.56 Makefile.def
*** Makefile.def 27 Jul 2005 20:20:08 -0000 1.56
--- Makefile.def 1 Aug 2005 15:17:29 -0000
*************** host_modules= { module= gnattools; };
*** 116,121 ****
--- 116,122 ----
target_modules = { module= libstdc++-v3; lib_path=.libs; raw_cxx=true; };
target_modules = { module= libmudflap; lib_path=.libs; };
target_modules = { module= libssp; lib_path=.libs; };
+ target_modules = { module= libsse2; lib_path=.libs; };
target_modules = { module= newlib; };
target_modules = { module= libgfortran; };
target_modules = { module= libobjc; };
Index: configure.in
===================================================================
RCS file: /cvs/gcc/gcc/configure.in,v
retrieving revision 1.361
diff -c -3 -p -r1.361 configure.in
*** configure.in 26 Jul 2005 15:56:54 -0000 1.361
--- configure.in 1 Aug 2005 15:17:29 -0000
*************** target_libraries="target-libiberty \
*** 148,153 ****
--- 148,154 ----
target-libstdc++-v3 \
target-libmudflap \
target-libssp \
+ target-libsse2 \
target-libgfortran \
${libgcj} \
target-libobjc \
*************** if test "${ENABLE_LIBSSP}" != "yes" ; th
*** 315,320 ****
--- 316,331 ----
noconfigdirs="$noconfigdirs target-libssp"
fi
+ dnl FIXME - enable on i?86 and multi-libbed x86_64
+ libsse2default=yes
+ AC_ARG_ENABLE(libsse2,
+ [ --enable-libsse2 Builds libsse2 directory],
+ ENABLE_LIBSSE2=$enableval,
+ ENABLE_LIBSSE2=$libsse2default)
+ if test "${ENABLE_LIBSSE2}" != "yes" ; then
+ noconfigdirs="$noconfigdirs target-libsse2"
+ fi
+
# Save it here so that, even in case of --enable-libgcj, if the Java
# front-end isn't enabled, we still get libgcj disabled.
libgcj_saved=$libgcj
Index: gcc/c-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.648
diff -c -3 -p -r1.648 c-common.c
*** gcc/c-common.c 24 Jul 2005 21:37:45 -0000 1.648
--- gcc/c-common.c 1 Aug 2005 15:17:30 -0000
*************** c_common_truthvalue_conversion (tree exp
*** 2494,2505 ****
return build_binary_op (NE_EXPR, expr, integer_zero_node, 1);
}
! static tree builtin_function_2 (const char *builtin_name, const char *name,
! tree builtin_type, tree type,
! enum built_in_function function_code,
! enum built_in_class cl, int library_name_p,
! bool nonansi_p,
! tree attrs);
/* Make a variant type in the proper way for C/C++, propagating qualifiers
down to the element type of an array. */
--- 2494,2505 ----
return build_binary_op (NE_EXPR, expr, integer_zero_node, 1);
}
! static void def_builtin_1 (enum built_in_function fncode,
! const char *name,
! enum built_in_class fnclass,
! tree fntype, tree libtype,
! bool both_p, bool fallback_p, bool nonansi_p,
! tree fnattrs, bool implicit_p);
/* Make a variant type in the proper way for C/C++, propagating qualifiers
down to the element type of an array. */
*************** c_common_nodes_and_builtins (void)
*** 3317,3352 ****
#define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, BOTH_P, FALLBACK_P, \
NONANSI_P, ATTRS, IMPLICIT, COND) \
if (NAME && COND) \
! { \
! tree decl; \
! \
! gcc_assert ((!BOTH_P && !FALLBACK_P) \
! || !strncmp (NAME, "__builtin_", \
! strlen ("__builtin_"))); \
! \
! if (!BOTH_P) \
! decl = lang_hooks.builtin_function (NAME, builtin_types[TYPE], \
! ENUM, \
! CLASS, \
! (FALLBACK_P \
! ? (NAME + strlen ("__builtin_")) \
! : NULL), \
! built_in_attributes[(int) ATTRS]); \
! else \
! decl = builtin_function_2 (NAME, \
! NAME + strlen ("__builtin_"), \
! builtin_types[TYPE], \
! builtin_types[LIBTYPE], \
! ENUM, \
! CLASS, \
! FALLBACK_P, \
! NONANSI_P, \
! built_in_attributes[(int) ATTRS]); \
! \
! built_in_decls[(int) ENUM] = decl; \
! if (IMPLICIT) \
! implicit_built_in_decls[(int) ENUM] = decl; \
! }
#include "builtins.def"
#undef DEF_BUILTIN
--- 3317,3327 ----
#define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, BOTH_P, FALLBACK_P, \
NONANSI_P, ATTRS, IMPLICIT, COND) \
if (NAME && COND) \
! def_builtin_1 (ENUM, NAME, CLASS, \
! builtin_types[(int) TYPE], \
! builtin_types[(int) LIBTYPE], \
! BOTH_P, FALLBACK_P, NONANSI_P, \
! built_in_attributes[(int) ATTRS], IMPLICIT);
#include "builtins.def"
#undef DEF_BUILTIN
*************** builtin_function_disabled_p (const char
*** 3436,3477 ****
}
! /* Possibly define a builtin function with one or two names. BUILTIN_NAME
! is an __builtin_-prefixed name; NAME is the ordinary name; one or both
! of these may be NULL (though both being NULL is useless).
! BUILTIN_TYPE is the type of the __builtin_-prefixed function;
! TYPE is the type of the function with the ordinary name. These
! may differ if the ordinary name is declared with a looser type to avoid
! conflicts with headers. FUNCTION_CODE and CL are as for
! builtin_function. If LIBRARY_NAME_P is nonzero, NAME is passed as
! the LIBRARY_NAME parameter to builtin_function when declaring BUILTIN_NAME.
! If NONANSI_P is true, the name NAME is treated as a non-ANSI name;
! ATTRS is the tree list representing the builtin's function attributes.
! Returns the declaration of BUILTIN_NAME, if any, otherwise
! the declaration of NAME. Does not declare NAME if flag_no_builtin,
! or if NONANSI_P and flag_no_nonansi_builtin. */
!
! static tree
! builtin_function_2 (const char *builtin_name, const char *name,
! tree builtin_type, tree type,
! enum built_in_function function_code,
! enum built_in_class cl, int library_name_p,
! bool nonansi_p, tree attrs)
! {
! tree bdecl = NULL_TREE;
! tree decl = NULL_TREE;
! if (builtin_name != 0)
! bdecl = lang_hooks.builtin_function (builtin_name, builtin_type,
! function_code, cl,
! library_name_p ? name : NULL, attrs);
!
! if (name != 0 && !flag_no_builtin && !builtin_function_disabled_p (name)
&& !(nonansi_p && flag_no_nonansi_builtin))
! decl = lang_hooks.builtin_function (name, type, function_code, cl,
! NULL, attrs);
! return (bdecl != 0 ? bdecl : decl);
}
/* Nonzero if the type T promotes to int. This is (nearly) the
--- 3411,3449 ----
}
! /* Worker for DEF_BUILTIN.
! Possibly define a builtin function with one or two names.
! Does not declare a non-__builtin_ function if flag_no_builtin, or if
! nonansi_p and flag_no_nonansi_builtin. */
! static void
! def_builtin_1 (enum built_in_function fncode,
! const char *name,
! enum built_in_class fnclass,
! tree fntype, tree libtype,
! bool both_p, bool fallback_p, bool nonansi_p,
! tree fnattrs, bool implicit_p)
! {
! tree decl, idecl = NULL;
! const char *libname;
!
! gcc_assert ((!both_p && !fallback_p)
! || !strncmp (name, "__builtin_",
! strlen ("__builtin_")));
!
! libname = name + strlen ("__builtin_");
! decl = lang_hooks.builtin_function (name, fntype, fncode, fnclass,
! (fallback_p ? libname : NULL),
! fnattrs);
! if (both_p
! && !flag_no_builtin && !builtin_function_disabled_p (libname)
&& !(nonansi_p && flag_no_nonansi_builtin))
! idecl = lang_hooks.builtin_function (libname, libtype, fncode, fnclass,
! NULL, fnattrs);
! built_in_decls[(int) fncode] = decl;
! if (implicit_p)
! implicit_built_in_decls[(int) fncode] = idecl ? idecl : decl;
}
/* Nonzero if the type T promotes to int. This is (nearly) the
Index: gcc/gcc.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gcc.c,v
retrieving revision 1.468
diff -c -3 -p -r1.468 gcc.c
*** gcc/gcc.c 25 Jul 2005 19:41:58 -0000 1.468
--- gcc/gcc.c 1 Aug 2005 15:17:30 -0000
*************** proper position among the other output f
*** 678,683 ****
--- 678,687 ----
#endif
#endif
+ #ifndef LINK_SSE2_SPEC
+ #define LINK_SSE2_SPEC ""
+ #endif
+
#ifndef LINK_PIE_SPEC
#ifdef HAVE_LD_PIE
#define LINK_PIE_SPEC "%{pie:-pie} "
*************** proper position among the other output f
*** 699,705 ****
%{s} %{t} %{u*} %{x} %{z} %{Z} %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
%{static:} %{L*} %(mfwrap) %(link_libgcc) %o %(mflib)\
%{fprofile-arcs|fprofile-generate|coverage:-lgcov}\
! %{!nostdlib:%{!nodefaultlibs:%(link_ssp)%(link_gcc_c_sequence)}}\
%{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}"
#endif
--- 703,709 ----
%{s} %{t} %{u*} %{x} %{z} %{Z} %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
%{static:} %{L*} %(mfwrap) %(link_libgcc) %o %(mflib)\
%{fprofile-arcs|fprofile-generate|coverage:-lgcov}\
! %{!nostdlib:%{!nodefaultlibs:%(link_sse2)%(link_ssp)%(link_gcc_c_sequence)}}\
%{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}"
#endif
*************** static const char *cc1_spec = CC1_SPEC;
*** 730,735 ****
--- 734,740 ----
static const char *cc1plus_spec = CC1PLUS_SPEC;
static const char *link_gcc_c_sequence_spec = LINK_GCC_C_SEQUENCE_SPEC;
static const char *link_ssp_spec = LINK_SSP_SPEC;
+ static const char *link_sse2_spec = LINK_SSE2_SPEC;
static const char *asm_spec = ASM_SPEC;
static const char *asm_final_spec = ASM_FINAL_SPEC;
static const char *link_spec = LINK_SPEC;
*************** static struct spec_list static_specs[] =
*** 1529,1534 ****
--- 1534,1540 ----
INIT_STATIC_SPEC ("cc1plus", &cc1plus_spec),
INIT_STATIC_SPEC ("link_gcc_c_sequence", &link_gcc_c_sequence_spec),
INIT_STATIC_SPEC ("link_ssp", &link_ssp_spec),
+ INIT_STATIC_SPEC ("link_sse2", &link_sse2_spec),
INIT_STATIC_SPEC ("endfile", &endfile_spec),
INIT_STATIC_SPEC ("link", &link_spec),
INIT_STATIC_SPEC ("lib", &lib_spec),
Index: gcc/config/i386/i386.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.c,v
retrieving revision 1.847
diff -c -3 -p -r1.847 i386.c
*** gcc/config/i386/i386.c 1 Aug 2005 03:54:54 -0000 1.847
--- gcc/config/i386/i386.c 1 Aug 2005 15:17:30 -0000
*************** static void ix86_init_builtins (void);
*** 912,917 ****
--- 912,919 ----
static rtx ix86_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
static const char *ix86_mangle_fundamental_type (tree);
static tree ix86_stack_protect_fail (void);
+ static void patch_sse_builtin (enum built_in_function, const char *);
+
/* This function is only used on Solaris. */
static void i386_solaris_elf_named_section (const char *, unsigned int, tree)
*************** static const struct builtin_description
*** 14037,14047 ****
--- 14039,14107 ----
{ MASK_SSE3, CODE_FOR_sse3_movsldup, 0, IX86_BUILTIN_MOVSLDUP, 0, 0 },
};
+ /* Patch some builtins with sseregparm attribute and
+ redirect their assembler_name. Note that we need
+ to change assembler_name for both __builtin_NAME
+ and NAME, while the (shared) type needs to be fixed
+ only once. */
+
+ static void
+ patch_sse_builtin (enum built_in_function fncode, const char *symbol)
+ {
+ tree sym = get_identifier (symbol);
+ tree fn = built_in_decls[fncode];
+ tree type = build_variant_type_copy (TREE_TYPE (fn));
+ TYPE_ATTRIBUTES (type)
+ = tree_cons (get_identifier ("sseregparm"),
+ NULL_TREE, TYPE_ATTRIBUTES (type));
+ TREE_TYPE (fn) = type;
+ SET_DECL_ASSEMBLER_NAME (fn, sym);
+ fn = implicit_built_in_decls[fncode];
+ if (fn)
+ {
+ TREE_TYPE (fn) = type;
+ SET_DECL_ASSEMBLER_NAME (fn, sym);
+ }
+ }
+
static void
ix86_init_builtins (void)
{
if (TARGET_MMX)
ix86_init_mmx_sse_builtins ();
+
+ if (ix86_fpmath == FPMATH_SSE
+ && TARGET_SSE2 && TARGET_SSELIBM)
+ {
+ patch_sse_builtin (BUILT_IN_ACOS, "__libm_sse2_acos");
+ patch_sse_builtin (BUILT_IN_ACOSF, "__libm_sse2_acosf");
+ patch_sse_builtin (BUILT_IN_ASIN, "__libm_sse2_asin");
+ patch_sse_builtin (BUILT_IN_ASINF, "__libm_sse2_asinf");
+ patch_sse_builtin (BUILT_IN_ATAN2, "__libm_sse2_atan2");
+ patch_sse_builtin (BUILT_IN_ATAN2F, "__libm_sse2_atan2f");
+ patch_sse_builtin (BUILT_IN_ATAN, "__libm_sse2_atan");
+ patch_sse_builtin (BUILT_IN_ATANF, "__libm_sse2_atanf");
+ patch_sse_builtin (BUILT_IN_COS, "__libm_sse2_cos");
+ patch_sse_builtin (BUILT_IN_COSF, "__libm_sse2_cosf");
+ patch_sse_builtin (BUILT_IN_EXP, "__libm_sse2_exp");
+ patch_sse_builtin (BUILT_IN_EXPF, "__libm_sse2_expf");
+ patch_sse_builtin (BUILT_IN_LOG10, "__libm_sse2_log10");
+ patch_sse_builtin (BUILT_IN_LOG10F, "__libm_sse2_log10f");
+ patch_sse_builtin (BUILT_IN_LOG, "__libm_sse2_log");
+ patch_sse_builtin (BUILT_IN_LOGF, "__libm_sse2_logf");
+ patch_sse_builtin (BUILT_IN_POW, "__libm_sse2_pow");
+ patch_sse_builtin (BUILT_IN_POWF, "__libm_sse2_powf");
+ patch_sse_builtin (BUILT_IN_SIN, "__libm_sse2_sin");
+ patch_sse_builtin (BUILT_IN_SINF, "__libm_sse2_sinf");
+ patch_sse_builtin (BUILT_IN_TAN, "__libm_sse2_tan");
+ patch_sse_builtin (BUILT_IN_TANF, "__libm_sse2_tanf");
+ #if 0
+ /* FIXME: Intel uses %xmm0 and %xmm1 as return value.
+ We cannot do this at the moment. */
+ patch_sse_builtin (BUILT_IN_SINCOS, "__libm_sse2_sincos");
+ patch_sse_builtin (BUILT_IN_SINCOSF, "__libm_sse2_sincosf");
+ #endif
+ }
}
/* Set up all the MMX/SSE builtins. This is not called if TARGET_MMX
Index: gcc/config/i386/i386.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.h,v
retrieving revision 1.443
diff -c -3 -p -r1.443 i386.h
*** gcc/config/i386/i386.h 31 Jul 2005 09:12:30 -0000 1.443
--- gcc/config/i386/i386.h 1 Aug 2005 15:17:30 -0000
*************** extern int x86_prefetch_sse;
*** 488,493 ****
--- 488,495 ----
#define EXTRA_SPECS \
{ "cc1_cpu", CC1_CPU_SPEC }, \
SUBTARGET_EXTRA_SPECS
+
+ #define LINK_SSE2_SPEC "%{msselibm:-lsse2 }"
/* target machine storage layout */
Index: gcc/config/i386/i386.opt
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.opt,v
retrieving revision 1.5
diff -c -3 -p -r1.5 i386.opt
*** gcc/config/i386/i386.opt 31 Jul 2005 09:12:33 -0000 1.5
--- gcc/config/i386/i386.opt 1 Aug 2005 15:17:30 -0000
*************** msseregparm
*** 201,206 ****
--- 201,210 ----
Target RejectNegative Mask(SSEREGPARM)
Use SSE register passing conventions for SF and DF mode
+ msselibm
+ Target Mask(SSELIBM)
+ Use SSE2 libm routines if using SSE math
+
msvr3-shlib
Target Report Mask(SVR3_SHLIB)
Uninitialized locals in .bss
Index: gcc/cp/call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.549
diff -c -3 -p -r1.549 call.c
*** gcc/cp/call.c 28 Jul 2005 18:08:46 -0000 1.549
--- gcc/cp/call.c 1 Aug 2005 15:17:30 -0000
*************** build_call (tree function, tree parms)
*** 314,329 ****
if (decl && DECL_CONSTRUCTOR_P (decl))
is_constructor = 1;
if (decl && ! TREE_USED (decl))
! {
! /* We invoke build_call directly for several library functions.
! These may have been declared normally if we're building libgcc,
! so we can't just check DECL_ARTIFICIAL. */
! gcc_assert (DECL_ARTIFICIAL (decl)
! || !strncmp (IDENTIFIER_POINTER (DECL_NAME (decl)),
! "__", 2));
! mark_used (decl);
! }
/* Don't pass empty class objects by value. This is useful
for tags in STL, which are used to control overload resolution.
--- 314,325 ----
if (decl && DECL_CONSTRUCTOR_P (decl))
is_constructor = 1;
+ /* We invoke build_call directly for several library functions.
+ These may have been declared normally if we're building libgcc,
+ so we can't just check DECL_ARTIFICIAL. In principle, cgraph
+ is supposed to handle this marking, so this is a (needed) hack. */
if (decl && ! TREE_USED (decl))
! mark_used (decl);
/* Don't pass empty class objects by value. This is useful
for tags in STL, which are used to control overload resolution.
Index: gcc/doc/invoke.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/invoke.texi,v
retrieving revision 1.662
diff -c -3 -p -r1.662 invoke.texi
*** gcc/doc/invoke.texi 31 Jul 2005 09:12:34 -0000 1.662
--- gcc/doc/invoke.texi 1 Aug 2005 15:17:30 -0000
*************** Objective-C and Objective-C++ Dialects}.
*** 515,521 ****
-mno-fp-ret-in-387 -msoft-float -msvr3-shlib @gol
-mno-wide-multiply -mrtd -malign-double @gol
-mpreferred-stack-boundary=@var{num} @gol
! -mmmx -msse -msse2 -msse3 -m3dnow @gol
-mthreads -mno-align-stringops -minline-all-stringops @gol
-mpush-args -maccumulate-outgoing-args -m128bit-long-double @gol
-m96bit-long-double -mregparm=@var{num} -msseregparm @gol
--- 515,521 ----
-mno-fp-ret-in-387 -msoft-float -msvr3-shlib @gol
-mno-wide-multiply -mrtd -malign-double @gol
-mpreferred-stack-boundary=@var{num} @gol
! -mmmx -msse -msse2 -msse3 -m3dnow -msselibm @gol
-mthreads -mno-align-stringops -minline-all-stringops @gol
-mpush-args -maccumulate-outgoing-args -m128bit-long-double @gol
-m96bit-long-double -mregparm=@var{num} -msseregparm @gol
*************** and disabled by these switches.
*** 9163,9168 ****
--- 9163,9174 ----
To have SSE/SSE2 instructions generated automatically from floating-point
code, see @option{-mfpmath=sse}.
+ @item -msselibm
+ @opindex msselibm
+ Use special versions of certain libm routines that come with an SSE
+ ABI and an SSE implementation. Useful together with @option{-mfpmath=sse}
+ to avoid moving values between SSE registers and the x87 FP stack.
+
@item -mpush-args
@itemx -mno-push-args
@opindex mpush-args