Re: [PATCH] S/390: Throw FE_INVALID exception in the fp2int libgcc routines

2014-02-06 Thread Andreas Krebbel
Here is a new version of the patch not limited to NaNs and Infs
anymore.

Bootstrapped and regtested on s390 with various options.

-Andreas-

2014-02-06  Andreas Krebbel  andreas.kreb...@de.ibm.com

* config/s390/32/_fixdfdi.c: Throw invalid exception if number
cannot be represented.
* config/s390/32/_fixsfdi.c: Likewise.
* config/s390/32/_fixtfdi.c: Likewise.
* config/s390/32/_fixunsdfdi.c: Likewise.
* config/s390/32/_fixunssfdi.c: Likewise.
* config/s390/32/_fixunstfdi.c: Likewise.

2014-02-06  Andreas Krebbel  andreas.kreb...@de.ibm.com

* gcc.target/s390/fp2int1.c: New testcase.

commit 080f0a28fd6f27f5d122e287a6f18481d253d433
Author: Andreas Krebbel kreb...@linux.vnet.ibm.com
Date:   Wed Jan 29 10:13:51 2014 +0100

S/390: libgcc: Throw INVALID exception for float-int conversions to
implement C99 Annex F.4.

diff --git a/gcc/testsuite/gcc.target/s390/fp2int1.c 
b/gcc/testsuite/gcc.target/s390/fp2int1.c
new file mode 100644
index 000..2176370
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/fp2int1.c
@@ -0,0 +1,95 @@
+/* Test for the 32 bit fp to 64 bit int conversion routines.
+   
+   On S/390 32 bit we use our own implementations in order to be IEEE
+   complaint as we are with our machine instructions.  These missed to
+   throw FE_INVALID exceptions in a bunch of cases.  */
+
+/* { dg-do run { target s390-*-* } } */
+/* { dg-options -O3 -mesa } */
+/* { dg-require-effective-target fenv_exceptions } */
+
+#define _GNU_SOURCE
+#include stdlib.h
+#include stdio.h
+#include fenv.h
+
+#define INFINITYf   (__builtin_inff())
+#define INFINITY(__builtin_inf())
+#define INFINITYl   (__builtin_infl())
+#define NANf(__builtin_nanf ())
+#define NAN (__builtin_nan ())
+#define NANl(__builtin_nanl ())
+
+#define TESTEXCEPT_FUNC(FUNC, TYPE_FROM, TYPE_TO)  \
+  TYPE_TO  \
+  __attribute__((noinline)) FUNC (TYPE_FROM a) \
+  {\
+asm volatile ( : : f (a)); \
+return (TYPE_TO)a; \
+  }
+
+#define TESTEXCEPT(FUNC, EXCEPT, EXPECT, VALUE, TYPE_TO)   \
+  {\
+TYPE_TO b; \
+feclearexcept (FE_ALL_EXCEPT); \
+b = FUNC (VALUE);  \
+if ((fetestexcept (EXCEPT)  (EXCEPT)) != EXPECT)  \
+  {
\
+   printf (FAIL in line: %d\n, __LINE__);\
+   abort ();   \
+  }
\
+  }
+
+#define TESTEXCEPT_FUNC_ALLFLOATS(FUNC, TYPE_TO)   \
+  TESTEXCEPT_FUNC (FUNC##_f, float, TYPE_TO);  \
+  TESTEXCEPT_FUNC (FUNC##_d, double, TYPE_TO); \
+  TESTEXCEPT_FUNC (FUNC##_l, long double, TYPE_TO);\
+
+#define TESTEXCEPT_ALLFLOATS(FUNC, EXCEPT, EXPECT, VALUE, TYPE_TO) \
+  TESTEXCEPT (FUNC##_f, EXCEPT, EXPECT, VALUE##f, TYPE_TO);\
+  TESTEXCEPT (FUNC##_d, EXCEPT, EXPECT, VALUE, TYPE_TO);   \
+  TESTEXCEPT (FUNC##_l, EXCEPT, EXPECT, VALUE##l, TYPE_TO);\
+
+TESTEXCEPT_FUNC_ALLFLOATS (a, unsigned long long);
+TESTEXCEPT_FUNC_ALLFLOATS (u, long long);
+
+
+int
+main ()
+{
+  /* Prevent getting signals.  */
+  fedisableexcept (FE_INVALID);
+
+  /* To unsigned long long */
+
+  TESTEXCEPT_ALLFLOATS (a, FE_INVALID, FE_INVALID, INFINITY, unsigned long 
long);
+  TESTEXCEPT_ALLFLOATS (a, FE_INVALID, FE_INVALID, -INFINITY, unsigned long 
long);
+  TESTEXCEPT_ALLFLOATS (a, FE_INVALID, FE_INVALID, NAN, unsigned long long);
+  TESTEXCEPT_ALLFLOATS (a, FE_INVALID, FE_INVALID, -NAN, unsigned long long);
+
+  /* Negative values -1.0 must not cause FE_INVALID.  */
+  TESTEXCEPT_ALLFLOATS (a, FE_INVALID, 0, -0x0.ffp0, unsigned long long);
+  /* -1.0 instead must.  */
+  TESTEXCEPT_ALLFLOATS (a, FE_INVALID, FE_INVALID, -0x1.0p+0, unsigned long 
long);
+  TESTEXCEPT_ALLFLOATS (a, FE_INVALID, 0, 0x1.0p+63, unsigned long long);
+  TESTEXCEPT_ALLFLOATS (a, FE_INVALID, FE_INVALID, 0x1.0p+64, unsigned long 
long);
+
+  /* To signed long long */
+
+  TESTEXCEPT_ALLFLOATS (u, FE_INVALID, FE_INVALID, INFINITY, long long);
+  TESTEXCEPT_ALLFLOATS (u, FE_INVALID, FE_INVALID, -INFINITY, long long);
+  TESTEXCEPT_ALLFLOATS (u, FE_INVALID, FE_INVALID, NAN, long long);
+  TESTEXCEPT_ALLFLOATS (u, FE_INVALID, FE_INVALID, -NAN, long long);
+
+  TESTEXCEPT_ALLFLOATS (u, FE_INVALID, 0, -0x1.0p+63, long long);
+  

Re: [PATCH] S/390: Throw FE_INVALID exception in the fp2int libgcc routines

2014-02-06 Thread Joseph S. Myers
I have no further comments on the patch.

-- 
Joseph S. Myers
jos...@codesourcery.com


[PATCH] S/390: Throw FE_INVALID exception in the fp2int libgcc routines

2014-01-30 Thread Andreas Krebbel
Hi,

our IEEE float to int conversion routines in libgcc do not throw the
FE_INVALID exceptions according to C99 Annex F.

Fixed with the attached patch.
This fixes the Glibc test-ldouble tests on s390:
 Failure: llrint (inf): Exception Invalid operation not set
 Failure: llrint (-inf): Exception Invalid operation not set
 Failure: llrint (qNaN): Exception Invalid operation not set
 Failure: llrint_tonearest (inf): Exception Invalid operation not set
 Failure: llrint_tonearest (-inf): Exception Invalid operation not set
 Failure: llrint_tonearest (qNaN): Exception Invalid operation not set
 Failure: llrint_towardzero (inf): Exception Invalid operation not set
 Failure: llrint_towardzero (-inf): Exception Invalid operation not set
 Failure: llrint_towardzero (qNaN): Exception Invalid operation not set
 Failure: llrint_downward (inf): Exception Invalid operation not set
 Failure: llrint_downward (-inf): Exception Invalid operation not set
 Failure: llrint_downward (qNaN): Exception Invalid operation not set
 Failure: llrint_upward (inf): Exception Invalid operation not set
 Failure: llrint_upward (-inf): Exception Invalid operation not set
 Failure: llrint_upward (qNaN): Exception Invalid operation not set
 Failure: llround (inf): Exception Invalid operation not set
 Failure: llround (-inf): Exception Invalid operation not set
 Failure: llround (qNaN): Exception Invalid operation not set

Glibc BZ: https://sourceware.org/bugzilla/show_bug.cgi?id=16449

I'll commit the patch after waiting a few days for comments.

Bye,

-Andreas-


2014-01-30  Andreas Krebbel  andreas.kreb...@de.ibm.com

* config/s390/32/_fixdfdi.c: Throw invalid exception if number
cannot be represented.
* config/s390/32/_fixsfdi.c: Likewise.
* config/s390/32/_fixtfdi.c: Likewise.
* config/s390/32/_fixunsdfdi.c: Likewise.
* config/s390/32/_fixunssfdi.c: Likewise.
* config/s390/32/_fixunstfdi.c: Likewise.

commit da26827014daa447835f41bf07f3e3eb3ffe0c75
Author: Andreas Krebbel kreb...@linux.vnet.ibm.com
Date:   Wed Jan 29 10:13:51 2014 +0100

S/390: libgcc: Throw INVALID exception for float-int conversions to
implement C99 Annex F.4.

diff --git a/libgcc/config/s390/32/_fixdfdi.c b/libgcc/config/s390/32/_fixdfdi.c
index 1c6954c..7178c01 100644
--- a/libgcc/config/s390/32/_fixdfdi.c
+++ b/libgcc/config/s390/32/_fixdfdi.c
@@ -46,6 +46,12 @@ union double_long {
 UDItype_x ll;
 };
 
+static __inline__ void
+fexceptdiv (float d, float e)
+{
+  __asm__ __volatile__ (debr %0,%1 : : f (d), f (e) );
+}
+
 DItype_x __fixdfdi (double a1);
 
 /* convert double to int */
@@ -73,7 +79,11 @@ __fixdfdi (double a1)
 /* NaN */
 
 if ((EXPD(dl1) == 0x7ff)  (FRACD_LL(dl1) != 0)) /* NaN */
-  return 0x8000ULL;
+  {
+   /* C99 Annex F.4 requires an invalid exception to be thrown.  */
+   fexceptdiv (0.0, 0.0);
+   return 0x8000ULL;
+  }
 
 /* Number big number  +/- inf */
 
@@ -81,6 +91,8 @@ __fixdfdi (double a1)
l = (long long)163;
if (!SIGND(dl1))
l--;
+   /* C99 Annex F.4 requires an invalid exception to be thrown.  */
+   fexceptdiv (0.0, 0.0);
return l;
 }
 
diff --git a/libgcc/config/s390/32/_fixsfdi.c b/libgcc/config/s390/32/_fixsfdi.c
index eaabd18..cea3b84 100644
--- a/libgcc/config/s390/32/_fixsfdi.c
+++ b/libgcc/config/s390/32/_fixsfdi.c
@@ -43,6 +43,12 @@ union float_long
 USItype_x l;
   };
 
+static __inline__ void
+fexceptdiv (float d, float e)
+{
+  __asm__ __volatile__ (debr %0,%1 : : f (d), f (e) );
+}
+
 DItype_x __fixsfdi (float a1);
 
 /* convert double to int */
@@ -70,7 +76,11 @@ __fixsfdi (float a1)
 /* NaN */
 
 if ((EXP(fl1) == 0xff)  (FRAC(fl1) != 0)) /* NaN */
-  return 0x8000ULL;
+  {
+   /* C99 Annex F.4 requires an invalid exception to be thrown.  */
+   fexceptdiv (0.0, 0.0);
+   return 0x8000ULL;
+  }
 
 /* Number big number  +/- inf */
 
@@ -78,6 +88,8 @@ __fixsfdi (float a1)
l = (long long)163;
if (!SIGN(fl1))
l--;
+   /* C99 Annex F.4 requires an invalid exception to be thrown.  */
+   fexceptdiv (0.0, 0.0);
return l;
 }
 
diff --git a/libgcc/config/s390/32/_fixtfdi.c b/libgcc/config/s390/32/_fixtfdi.c
index 51807d1..d17c516 100644
--- a/libgcc/config/s390/32/_fixtfdi.c
+++ b/libgcc/config/s390/32/_fixtfdi.c
@@ -50,6 +50,12 @@ union double_long {
   UDItype_x ll[2];   /* 64 bit parts: 0 upper, 1 lower */
 };
 
+static __inline__ void
+fexceptdiv (float d, float e)
+{
+  __asm__ __volatile__ (debr %0,%1 : : f (d), f (e) );
+}
+
 DItype_x __fixtfdi (long double a1);
 
 /* convert double to unsigned int */
@@ -77,7 +83,11 @@ __fixtfdi (long double a1)
 
 /* NaN: All exponent bits set and a nonzero fraction.  */
 if ((EXPD(dl1) == 0x7fff)  !FRACD_ZERO_P (dl1))
-  return 0x8000ULL;
+  {
+   /* C99 Annex F.4 requires an 

Re: [PATCH] S/390: Throw FE_INVALID exception in the fp2int libgcc routines

2014-01-30 Thread Joseph S. Myers
On Thu, 30 Jan 2014, Andreas Krebbel wrote:

 @@ -81,6 +91,8 @@ __fixdfdi (double a1)
   l = (long long)163;
   if (!SIGND(dl1))
   l--;
 + /* C99 Annex F.4 requires an invalid exception to be thrown.  */
 + fexceptdiv (0.0, 0.0);
   return l;

My understanding of this code is that the condition exp = 11 means a 
number with magnitude at least 0x1p63.  If the number is exactly -0x1p63, 
then the result of the most negative long long value should not involve 
the invalid exception.

 @@ -78,6 +88,8 @@ __fixsfdi (float a1)
   l = (long long)163;
   if (!SIGN(fl1))
   l--;
 + /* C99 Annex F.4 requires an invalid exception to be thrown.  */
 + fexceptdiv (0.0, 0.0);
   return l;

Likewise.

 @@ -90,6 +100,8 @@ __fixtfdi (long double a1)
 or more.  */
  if (exp = 0)
{
 + /* C99 Annex F.4 requires an invalid exception to be thrown.  */
 + fexceptdiv (0.0, 0.0);
   l = 1ULL  63; /* long long min */
   return SIGND (dl1) ? l : l - 1;

Likewise, except in this case there are also values whose integer part is 
LLONG_MIN but whose fractional part is nonzero, for which invalid should 
also not be raised.

(This complication only arises for conversion to signed integers, not for 
conversion to unsigned.  But for the conversions to unsigned, you need to 
raise invalid for arguments = -1, which your patch doesn't seem to do.)

-- 
Joseph S. Myers
jos...@codesourcery.com