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]

Irix6 native long double libcalls progress report (and problem)


I got pretty far getting Irix6 to use it's native libc long double
routines.  I managed to come up with a patch and run some timing
tests, for long double ops in isolation I'm getting speedups from 5x
to 20x over the gcc routines depending on the operation performed.

So far so good.  In the case of the comparison ops, they don't have
the same return values that gcc expects, so I commented them out.  And
in another case, the gcc routines are better, so I commented out those
too.  What's left is in the patch at the end of this message.

When I ran the testsuite however, I get one new failure in
execute/conversion.c.  The problem boils down to this:

 > long double
 > ull2ld(u)
 >      unsigned long long int u;
 > {
 >   return u;
 > }
 > 

Then we crash on this code:

 >   if (ull2ld(~0ULL) != (long double) ~0ULL)
 >     abort();

I.e. supposedly the value passed through and converted in a function
is different than the same constant cast inline.

I added some code to check out what we're actually getting:


 > #include <stdio.h>
 > extern void abort(void);
 > 
 > long double
 > ull2ld(u)
 >      unsigned long long int u;
 > {
 >   return u;
 > }
 > 
 > int main()
 > {
 >   fprintf (stderr, "%.25Le\n%.25Le\n%Le\n", ull2ld(~0ULL),
 > 	   (long double) ~0ULL, ull2ld(~0ULL) - (long double) ~0ULL);
 >   {
 >     union f { long double ld; unsigned long long ll[2]; }
 >     f1 = { ull2ld(~0ULL) }, f2 = { (long double) ~0ULL };
 >     
 >     fprintf (stderr, "%llx %016llx\n%llx %016llx\n",
 > 	     f1.ll[0], f1.ll[1], f2.ll[0], f2.ll[1]);
 >   }
 > 
 >   if (ull2ld(~0ULL) != (long double) ~0ULL)
 >     abort();
 >   
 >   return 0;
 > }
 >  

With gcc-3.3 from last night plus the patch, it yields:

1.8446744073709551615000000e+19
1.8446744073709551615000000e+19
0.000000e+00
43f0000000000000 bff0000000000000
43efffffffffffff 409ffc0000000000
Abort (core dumped)

As you can see, the numbers are equal in value.  To see whether the
value was different in some far out Nth decimal place, I subtracted
them and it results in zero point zero.

But the bit patterns are different!  And I'm guessing that this
confuses the gcc comparison function.

What's going on here?  Ideas?

		Thanks,
		--Kaveh


2003-01-30  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>

	* mips/iris6.h (INIT_NATIVE_TFP_OPTABS): Define.
	* config.gcc: Set INIT_SUBTARGET_OPTABS to INIT_NATIVE_TFP_OPTABS
	for irix6 when not enabling "gofast" routines.

diff -rup orig/egcc-3.3-CVS20030129/gcc/config/mips/iris6.h egcc-3.3-CVS20030129/gcc/config/mips/iris6.h
--- orig/egcc-3.3-CVS20030129/gcc/config/mips/iris6.h	Mon Jan 27 22:31:46 2003
+++ egcc-3.3-CVS20030129/gcc/config/mips/iris6.h	Thu Jan 30 08:56:54 2003
@@ -511,3 +511,35 @@ do {									 \
 %{mabi=32: -32}%{mabi=n32: -n32}%{mabi=64: -64}%{!mabi*: -n32}"
 
 #define MIPS_TFMODE_FORMAT ibm_extended_format
+
+/* Faster long double routines from irix6 libc.  */
+#define INIT_NATIVE_TFP_OPTABS \
+do { \
+  add_optab->handlers[(int) TFmode].libfunc = init_one_libfunc ("__q_add"); \
+  sub_optab->handlers[(int) TFmode].libfunc = init_one_libfunc ("__q_sub"); \
+  smul_optab->handlers[(int) TFmode].libfunc = init_one_libfunc ("__q_mul"); \
+  sdiv_optab->handlers[(int) TFmode].libfunc = init_one_libfunc ("__q_div"); \
+  neg_optab->handlers[(int) TFmode].libfunc = init_one_libfunc ("__q_neg"); \
+\
+  extendsftf2_libfunc = init_one_libfunc ("__q_ext"); \
+  extenddftf2_libfunc = init_one_libfunc ("__q_extd"); \
+  trunctfsf2_libfunc = init_one_libfunc ("__sngl_q"); \
+  trunctfdf2_libfunc = init_one_libfunc ("__dble_q"); \
+\
+  /* These routines return 0/1, we need tri-state -1,0.1.  */ \
+  /*eqtf2_libfunc = init_one_libfunc ("__q_eq");*/ \
+  /*netf2_libfunc = init_one_libfunc ("__q_ne");*/ \
+  /*gttf2_libfunc = init_one_libfunc ("__q_gt");*/ \
+  /*getf2_libfunc = init_one_libfunc ("__q_ge");*/ \
+  /*lttf2_libfunc = init_one_libfunc ("__q_lt");*/ \
+  /*letf2_libfunc = init_one_libfunc ("__q_le");*/ \
+\
+  /* These two routines are actually slower.  */ \
+  /*fixtfsi_libfunc = init_one_libfunc ("__ji_qint");*/ \
+  /*fixunstfsi_libfunc = init_one_libfunc ("__ji_quint");*/ \
+  fixtfdi_libfunc = init_one_libfunc ("__ki_qint"); \
+  fixunstfdi_libfunc = init_one_libfunc ("__ki_quint"); \
+\
+  floatsitf_libfunc = init_one_libfunc ("__q_flotj"); \
+  floatditf_libfunc = init_one_libfunc ("__q_flotk"); \
+} while (0)
diff -rup orig/egcc-3.3-CVS20030127/gcc/config.gcc egcc-3.3-CVS20030127/gcc/config.gcc
--- orig/egcc-3.3-CVS20030127/gcc/config.gcc	2003-01-04 17:00:25.000000000 -0500
+++ egcc-3.3-CVS20030127/gcc/config.gcc	2003-01-28 14:39:51.670349000 -0500
@@ -2879,6 +2879,7 @@ mips*-*-*)
 		tm_file="gofast.h $tm_file"
 		tmake_file="mips/t-gofast $tmake_file"
 	else
+		tm_defines="INIT_SUBTARGET_OPTABS=INIT_NATIVE_TFP_OPTABS $tm_defines"
 		tmake_file="mips/t-mips $tmake_file"
 	fi
 	;;


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