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] Add word-sized conversion functions to libgcc2


This is a rewrite of my previous patch from
(http://gcc.gnu.org/ml/gcc-patches/2006-05/msg00350.html).  As I
mention in the thread I am moving the solution into libgcc2.[ch] to
avoid duplicate DI conversion functions in case of MIPS32.

To recap first, for soft-float, libgcc2.c provides one set of
functions for each floating-point mode to convert to or from
double-word integer mode.  The implementations are built up from
simpler conversion functions from fp-bit or libgcc2.c itself.  One
exception is fixuns where in addition to double-word single-word
conversion functions are also provided by libgcc2.c.

Another detail about libgcc2 and fp-bit is that the former defines
functions for double-word integer mode whereas the latter does it for
SImode.  That means that on 64-bit we end up missing the
DImode/single-word conversion functions.  64-bit ports supporting
soft-float usually create port-specific routines based on expanding
libgcc2.c to fix around this problem, see ppc64-fp.c for an example.

Instead of doing the same thing for MIPS64, this patch is an attempt
to generalize the idea and to have the compiler do the expansion.
Ports can now request 8 additional libgcc2 functions.  The name
convention follows the existing logic.  E.g. currently if you ask for
the LIB2FUNC _fixsfdi on 64-bit, a definition for _fixsfti will be
added to libgcc.a.  So along the same "logic" for example the new
libgcc2 function fixsfsi which will define conversion between SF and
DI on 64-bit.

The idea of generating word-sized conversion functions is to pretend
that the word size is SI while generating the "double-word" (DImode)
conversion functions.

The new functions are only enabled if MIN_UNITS_PER_WORD is more than
4.  This fixes the problem of 32-bit multilib duplicates in my
previous patch.  Also at this point the new functions have to be
explicitly requested by the port to avoid duplicates if there is
port-local version of the same functions.

Just like ppc64-fp.c I also had to find a solution for the recursion
between fixsfdi and fixunsfdi.  To describe the problem: for 32-bit
this how fix* and fixuns* functions call each other:

		fix		fixuns

  SF<->SI	fp-bit	<-----	libgcc2 <-.
                                          |
  SF<->DI	libgcc2 ----->  libgcc2 --'


For 64-bit, libgcc2 functions a "pushed down" to the next widest mode
or:

		fix		fixuns

  SF<->SI	fp-bit	<-----	        <-.
                                          |
  SF<->DI               <-----  libgcc2   |
                                          |
  SF<->TI	libgcc2 ----->  libgcc2 --'

If I simply provide fixsfdi and fixunssfsi using the usual 32-bit
definitions (i.e. merge the two figures above) I get an infinite loop
between fixsfdi and fixunsfdi:

		fix		fixuns

  SF<->SI	fp-bit	<-----	libgcc2 <-.
                                          |
  SF<->DI       libgcc2 <---->  libgcc2   |
                                          |
  SF<->TI	libgcc2 ----->  libgcc2 --'

PowerPC resolves this problem by calling a local version of fixunssfdi
from fixsfdi instead of the one in libgcc.a which in turn will call
fixunsfsi.  My solution is to arrange libgcc2.h so that we generate
fixunssfdi using the fixunssfdi rather than the fixunssfsi template
which will has the same effect as the PowerPC hack (see comment in the
patch for some more details):

		fix		fixuns

  SF<->SI	fp-bit	<-----	libgcc2 <-.-.
                                          | |
  SF<->DI       libgcc2 ----->  libgcc2 --' |
                                            |
  SF<->TI	libgcc2 ----->  libgcc2 ----'

With the patch, 64-bit soft-float testresults are back to where they
were before Roger's patch (+162 passes) with one exception.  The
failure of gcc.dg/ftrapv-2.c seems to unrelated to this isssue and
soft-float altogether because it fails with hard-float too.  I also
tested default and -msoft-float/-mips32 multilibs with no regressions.
I also manually checked that there were no duplicate functions in any
of the libgcc multilibs.  This is all on mipsisa64-elf.  I also
bootstrapped and regtested on i686-pc-linux-gnu.

OK for mainline and later for 4.1?

Adam

	* Makefile.in (LIB2FUNCS_OPT): New variable.
	(libgcc.mk): PAss it to mklibgcc.
	* mklibgcc.in (lib2funcs): Append $LIB2FUNCS_OPT.
	* libgcc2.h: Add support for new LIB2FUNCS fixsfsi, fixdfsi,
	fixunssfhi, fixunsdfhi, fixunssfsi, fixunsdfsi, floatsisf,
	floatsidf, floatunsisf and floatunsidf.  Use the fixuns*di
	template for fixunssfsi and fixunsdfsi.
	* config/mips/t-mips (LIB2FUNCS_OPT): Define it.

Index: libgcc2.h
===================================================================
--- libgcc2.h	(revision 113754)
+++ libgcc2.h	(working copy)
@@ -191,6 +191,65 @@ typedef int word_type __attribute__ ((mo
 #define float bogus_type
 #define double bogus_type
 
+/* Provide single-word conversion functions for 64-bit targets.  We do
+   this by relying on the double-word patterns but pretending the word
+   size is SImode.  */
+#if (MIN_UNITS_PER_WORD > 4						\
+     && (defined (L_fixsfsi) || defined (L_fixdfsi)			\
+	 || defined (L_fixunssfhi) || defined (L_fixunsdfhi)		\
+	 || defined (L_fixunssfsi) || defined (L_fixunsdfsi)		\
+	 || defined (L_floatsisf) || defined (L_floatsidf)		\
+	 || defined (L_floatunsisf) || defined (L_floatunsidf)))
+# define WORD_CONVERSION_FUNC 1
+# ifdef L_fixsfsi
+#  undef  L_fixsfsi
+#  define L_fixsfdi
+# endif
+# ifdef L_fixdfsi
+#  undef  L_fixdfsi
+#  define L_fixdfdi
+# endif
+/* Generate single-word fixuns with the fixuns*di template so that it
+   relies on half-word fixuns for its implementation.  If we used the
+   fixuns*si template the function would call single-word fix leading
+   to an infinite loop.  This is because single-word fix is
+   implemented with the fix*di pattern which calls fixuns.  */
+# ifdef L_fixunssfsi
+#  undef  L_fixunssfsi
+#  define L_fixunssfdi
+# endif
+# ifdef L_fixunsdfsi
+#  undef  L_fixunsdfsi
+#  define L_fixunsdfdi
+# endif
+# ifdef L_fixunssfhi
+#  undef  L_fixunssfhi
+#  define L_fixunssfsi
+# endif
+# ifdef L_fixunsdfhi
+#  undef  L_fixunsdfhi
+#  define L_fixunsdfsi
+# endif
+# ifdef L_floatsisf
+#  undef  L_floatsisf
+#  define L_floatdisf
+# endif
+# ifdef L_floatsidf
+#  undef  L_floatsidf
+#  define L_floatdidf
+# endif
+# ifdef L_floatunsisf
+#  undef  L_floatunsisf
+#  define L_floatundisf
+# endif
+# ifdef L_floatunsidf
+#  undef  L_floatunsidf
+#  define L_floatundidf
+# endif
+#else
+# define WORD_CONVERSION_FUNC 0
+#endif
+
 /* Versions prior to 3.4.4 were not taking into account the word size for
    the 5 trapping arithmetic functions absv, addv, subv, mulv and negv.  As
    a consequence, the si and di variants were always and the only ones emitted.
@@ -201,7 +260,7 @@ typedef int word_type __attribute__ ((mo
    turns out that no platform would define COMPAT_DIMODE_TRAPPING_ARITHMETIC
    if it existed.  */
 
-#if MIN_UNITS_PER_WORD > 4
+#if MIN_UNITS_PER_WORD > 4 && !WORD_CONVERSION_FUNC
 #define W_TYPE_SIZE (8 * BITS_PER_UNIT)
 #define Wtype	DItype
 #define UWtype	UDItype
@@ -213,7 +272,8 @@ typedef int word_type __attribute__ ((mo
 #define __NDW(a,b)	__ ## a ## ti ## b
 #define COMPAT_SIMODE_TRAPPING_ARITHMETIC
 #elif MIN_UNITS_PER_WORD > 2 \
-      || (MIN_UNITS_PER_WORD > 1 && LONG_LONG_TYPE_SIZE > 32)
+      || (MIN_UNITS_PER_WORD > 1 && LONG_LONG_TYPE_SIZE > 32) \
+      || WORD_CONVERSION_FUNC
 #define W_TYPE_SIZE (4 * BITS_PER_UNIT)
 #define Wtype	SItype
 #define UWtype	USItype
Index: mklibgcc.in
===================================================================
--- mklibgcc.in	(revision 113754)
+++ mklibgcc.in	(working copy)
@@ -12,6 +12,7 @@
 # LIB1ASMFUNCS
 # LIB2FUNCS_ST
 # LIB2FUNCS_EXCLUDE
+# LIB2FUNCS_OPT
 # LIBGCOV
 # LIB2ADD
 # LIB2ADD_ST 
@@ -64,7 +65,7 @@ echo 'dirs = libgcc'
 echo
 
 # Library members defined in libgcc2.c.
-lib2funcs='_muldi3 _negdi2 _lshrdi3 _ashldi3 _ashrdi3
+lib2funcs="_muldi3 _negdi2 _lshrdi3 _ashldi3 _ashrdi3
 	_cmpdi2 _ucmpdi2 _floatdidf _floatdisf _fixunsdfsi _fixunssfsi
 	_fixunsdfdi _fixdfdi _fixunssfdi _fixsfdi _fixxfdi _fixunsxfdi
 	_floatdixf _fixunsxfsi _fixtfdi _fixunstfdi _floatditf _clear_cache
@@ -73,7 +74,8 @@ lib2funcs='_muldi3 _negdi2 _lshrdi3 _ash
 	_ffssi2 _ffsdi2 _clz _clzsi2 _clzdi2 _ctzsi2 _ctzdi2 _popcount_tab
 	_popcountsi2 _popcountdi2 _paritysi2 _paritydi2 _powisf2 _powidf2
 	_powixf2 _powitf2 _mulsc3 _muldc3 _mulxc3 _multc3 _divsc3 _divdc3
-	_divxc3 _divtc3 _floatundidf _floatundisf _floatundixf _floatunditf'
+	_divxc3 _divtc3 _floatundidf _floatundisf _floatundixf _floatunditf
+	$LIB2FUNCS_OPT"
 
 # Disable SHLIB_LINK if shared libgcc not enabled.
 if [ "@enable_shared@" = "no" ]; then
Index: Makefile.in
===================================================================
--- Makefile.in	(revision 113754)
+++ Makefile.in	(working copy)
@@ -614,6 +614,9 @@ LIB2FUNCS_STATIC_EXTRA =
 # List of functions not to build from libgcc2.c.
 LIB2FUNCS_EXCLUDE =
 
+# List of optional functions to build from libgcc2.c.
+LIB2FUNCS_OPT =
+
 # Target sfp-machine.h file.
 SFP_MACHINE =
 
@@ -1405,6 +1408,7 @@ libgcc.mk: config.status Makefile mklibg
 	LIB1ASMFUNCS='$(LIB1ASMFUNCS)' \
 	LIB2FUNCS_ST='$(LIB2FUNCS_ST)' \
 	LIB2FUNCS_EXCLUDE='$(LIB2FUNCS_EXCLUDE)' \
+	LIB2FUNCS_OPT='$(LIB2FUNCS_OPT)' \
 	LIBGCOV='$(LIBGCOV)' \
 	LIB2ADD='$(LIB2ADD)' \
 	LIB2ADD_ST='$(LIB2ADD_ST)' \
Index: config/mips/t-mips
===================================================================
--- config/mips/t-mips	(revision 113754)
+++ config/mips/t-mips	(working copy)
@@ -19,3 +19,6 @@ fp-bit.c: $(srcdir)/config/fp-bit.c
 	echo '#endif' >> fp-bit.c
 	echo '#define QUIET_NAN_NEGATED' >> fp-bit.c
 	cat $(srcdir)/config/fp-bit.c >> fp-bit.c
+
+LIB2FUNCS_OPT = _fixsfsi _fixdfsi _fixunssfhi _fixunsdfhi \
+  _floatsisf _floatsidf _floatunsisf _floatunsidf


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