aarch64 sim fp min/max number bug fix

Message ID CABXYE2Wx+cVEaUF2OZb5-wtUd9hkLB6QcCDzuvHkqm-8OuPGQQ@mail.gmail.com
State New, archived
Headers

Commit Message

Jim Wilson Jan. 1, 2017, 5:16 p.m. UTC
  The fp min/max number routines are using fpclassify to try to
distinguish between a nan and a number, but this is handling zero,
inf, and subnormals incorrectly.  We get the right result if we just
use isnan.

The testcase works with the patch, and fails without the patch.  The
patch also reduces GCC C testsuite failures from 2416 to 2407.

Jim
  

Comments

Nick Clifton Jan. 3, 2017, 2:38 p.m. UTC | #1
Hi Jim

> The fp min/max number routines are using fpclassify to try to
> distinguish between a nan and a number, but this is handling zero,
> inf, and subnormals incorrectly.  We get the right result if we just
> use isnan.
> 
> The testcase works with the patch, and fails without the patch.  The
> patch also reduces GCC C testsuite failures from 2416 to 2407.

Approved - please apply.

Cheers
  Nick
  

Patch

	sim/aarch64/
	* simulator.c (fmaxnm): Use isnan instead of fpclassify.
	(fminnm, dmaxnm, dminnm): Likewise.

	sim/testsuite/sim/aarch64/
	* fminnm.s: New.

diff --git a/sim/aarch64/simulator.c b/sim/aarch64/simulator.c
index be3d6c7..cf65a51 100644
--- a/sim/aarch64/simulator.c
+++ b/sim/aarch64/simulator.c
@@ -3831,13 +3831,13 @@  do_vec_MLA (sim_cpu *cpu)
 static float
 fmaxnm (float a, float b)
 {
-  if (fpclassify (a) == FP_NORMAL)
+  if (! isnan (a))
     {
-      if (fpclassify (b) == FP_NORMAL)
+      if (! isnan (b))
 	return a > b ? a : b;
       return a;
     }
-  else if (fpclassify (b) == FP_NORMAL)
+  else if (! isnan (b))
     return b;
   return a;
 }
@@ -3845,13 +3845,13 @@  fmaxnm (float a, float b)
 static float
 fminnm (float a, float b)
 {
-  if (fpclassify (a) == FP_NORMAL)
+  if (! isnan (a))
     {
-      if (fpclassify (b) == FP_NORMAL)
+      if (! isnan (b))
 	return a < b ? a : b;
       return a;
     }
-  else if (fpclassify (b) == FP_NORMAL)
+  else if (! isnan (b))
     return b;
   return a;
 }
@@ -3859,13 +3859,13 @@  fminnm (float a, float b)
 static double
 dmaxnm (double a, double b)
 {
-  if (fpclassify (a) == FP_NORMAL)
+  if (! isnan (a))
     {
-      if (fpclassify (b) == FP_NORMAL)
+      if (! isnan (b))
 	return a > b ? a : b;
       return a;
     }
-  else if (fpclassify (b) == FP_NORMAL)
+  else if (! isnan (b))
     return b;
   return a;
 }
@@ -3873,13 +3873,13 @@  dmaxnm (double a, double b)
 static double
 dminnm (double a, double b)
 {
-  if (fpclassify (a) == FP_NORMAL)
+  if (! isnan (a))
     {
-      if (fpclassify (b) == FP_NORMAL)
+      if (! isnan (b))
 	return a < b ? a : b;
       return a;
     }
-  else if (fpclassify (b) == FP_NORMAL)
+  else if (! isnan (b))
     return b;
   return a;
 }
diff --git a/sim/testsuite/sim/aarch64/fminnm.s b/sim/testsuite/sim/aarch64/fminnm.s
new file mode 100644
index 0000000..43ccd7c
--- /dev/null
+++ b/sim/testsuite/sim/aarch64/fminnm.s
@@ -0,0 +1,82 @@ 
+# mach: aarch64
+
+# Check the FP min/max number instructions: fminnm, fmaxnm, dminnm, dmaxnm.
+# For min, check 2/1, 1/0, -1/-Inf.
+# For max, check 1/2, -1/0, 1/+inf.
+
+.include "testutils.inc"
+
+	start
+	fmov s0, #2.0
+	fmov s1, #1.0
+	fminnm s2, s0, s1
+	fcmp s2, s1
+	bne .Lfailure
+	fmov d0, #2.0
+	fmov d1, #1.0
+	fminnm d2, d0, d1
+	fcmp d2, d1
+	bne .Lfailure
+
+	fmov s0, #1.0
+	fmov s1, wzr
+	fminnm s2, s0, s1
+	fcmp s2, s1
+	bne .Lfailure
+	fmov d0, #1.0
+	fmov d1, xzr
+	fminnm d2, d0, d1
+	fcmp d2, d1
+	bne .Lfailure
+
+	fmov s0, #-1.0
+	fmov s1, wzr
+	fdiv s1, s0, s1
+	fminnm s2, s0, s1
+	fcmp s2, s1
+	bne .Lfailure
+	fmov d0, #-1.0
+	fmov d1, xzr
+	fdiv d1, d0, d1
+	fminnm d1, d0, d1
+	fcmp d0, d0
+	bne .Lfailure
+
+	fmov s0, #1.0
+	fmov s1, #2.0
+	fmaxnm s2, s0, s1
+	fcmp s2, s1
+	bne .Lfailure
+	fmov d0, #1.0
+	fmov d1, #2.0
+	fmaxnm d2, d0, d1
+	fcmp d2, d1
+	bne .Lfailure
+
+	fmov s0, #-1.0
+	fmov s1, wzr
+	fmaxnm s2, s0, s1
+	fcmp s2, s1
+	bne .Lfailure
+	fmov d0, #-1.0
+	fmov d1, xzr
+	fmaxnm d2, d0, d1
+	fcmp d2, d1
+	bne .Lfailure
+
+	fmov s0, #1.0
+	fmov s1, wzr
+	fdiv s1, s0, s1
+	fmaxnm s2, s0, s1
+	fcmp s2, s1
+	bne .Lfailure
+	fmov d0, #1.0
+	fmov d1, xzr
+	fdiv d1, d0, d1
+	fmaxnm d1, d0, d1
+	fcmp d0, d0
+	bne .Lfailure
+
+	pass
+.Lfailure:
+	fail