From f787591e993d581a0abcc41b52bcace14465a6b8 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Mon, 18 Apr 2016 06:35:21 -0700 Subject: [PATCH 1/4] More tests! This adds more floating point rounding tests, more expression optimizer bait tests, more real-world floating point bug tests, and more comments. --- ml-proto/TestingTodo.md | 12 +- ml-proto/test/conversions.wast | 24 ++ ml-proto/test/f32.wast | 3 + ml-proto/test/f32_cmp.wast | 3 + ml-proto/test/f64.wast | 3 + ml-proto/test/f64_cmp.wast | 3 + ml-proto/test/float_exprs.wast | 592 ++++++++++++++++++++++++++++- ml-proto/test/float_literals.wast | 2 + ml-proto/test/float_memory.wast | 165 +++++--- ml-proto/test/float_misc.wast | 204 +++++++++- ml-proto/test/int_exprs.wast | 3 + ml-proto/test/nan-propagation.wast | 2 + 12 files changed, 948 insertions(+), 68 deletions(-) diff --git a/ml-proto/TestingTodo.md b/ml-proto/TestingTodo.md index 5e6ecbd678..a0cdd22b59 100644 --- a/ml-proto/TestingTodo.md +++ b/ml-proto/TestingTodo.md @@ -49,8 +49,8 @@ Floating point semantics: - ~~test that nearestint doesn't do JS-style Math.round or C-style round(3) rounding~~ - ~~test that signalling NaN doesn't cause weirdness~~ - ~~test that signalling/quiet NaNs can have sign bits and payloads in literals~~ - - test that conversion from int32/int64 to float32 rounds correctly - - test that [relaxed optimizations](https://gcc.gnu.org/wiki/FloatingPointMath) are not done + - ~~test that conversion from int32/int64 to float32 rounds correctly~~ + - ~~test that [relaxed optimizations](https://gcc.gnu.org/wiki/FloatingPointMath) are not done~~ Linear memory semantics: - test that loading from null works @@ -82,13 +82,14 @@ Expression optimizer bait: - ~~test that floating-point division by immediate 0 and -0 is defined~~ - ~~test that floating-point (x*y)/y isn't folded to x~~ - ~~test that floating-point (x+y)-y isn't folded to x~~ - - test that ult/ugt/etc (formed with a not operator) aren't folded to oge/ole/etc. + - ~~test that ult/ugt/etc (formed with a not operator) aren't folded to oge/ole/etc.~~ - ~~test that floating point add/mul aren't reassociated even when tempting~~ - ~~test that floating point mul+add isn't folded to fma even when tempting~~ - ~~test that floating point sqrt(x*x+y*y) isn't folded to hypot even when tempting~~ - ~~test that 1/x isn't translated into reciprocal-approximate~~ - ~~test that 1/sqrt(x) isn't approximated either~~ - ~~test that fp division by non-power-2 constant gets full precision (isn't a multiply-by-reciprocal deal)?~~ + - ~~test that x Date: Mon, 18 Apr 2016 12:45:12 -0700 Subject: [PATCH 2/4] Test that f32.nearest isn't implemented naively. --- ml-proto/test/float_misc.wast | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ml-proto/test/float_misc.wast b/ml-proto/test/float_misc.wast index 6833362cf7..32ff6cba66 100644 --- a/ml-proto/test/float_misc.wast +++ b/ml-proto/test/float_misc.wast @@ -519,6 +519,16 @@ (assert_return (invoke "f64.floor" (f64.const -0x1.fffffffffffffp-1)) (f64.const -1.0)) (assert_return (invoke "f64.floor" (f64.const -0x1p-1022)) (f64.const -1.0)) +;; Test that nearest isn't implemented naively. +;; http://blog.frama-c.com/index.php?post/2013/05/02/nearbyintf1 +;; http://blog.frama-c.com/index.php?post/2013/05/04/nearbyintf3 +(assert_return (invoke "f32.nearest" (f32.const 0x1.000002p+23)) (f32.const 0x1.000002p+23)) +(assert_return (invoke "f32.nearest" (f32.const 0x1.000004p+23)) (f32.const 0x1.000004p+23)) +(assert_return (invoke "f32.nearest" (f32.const 0x1.fffffep-2)) (f32.const 0.0)) +(assert_return (invoke "f64.nearest" (f64.const 0x1.0000000000001p+52)) (f64.const 0x1.0000000000001p+52)) +(assert_return (invoke "f64.nearest" (f64.const 0x1.0000000000002p+52)) (f64.const 0x1.0000000000002p+52)) +(assert_return (invoke "f64.nearest" (f64.const 0x1.fffffffffffffp-2)) (f64.const 0.0)) + ;; Nearest should not round halfway cases away from zero (as C's round(3) does) ;; or up (as JS's Math.round does). (assert_return (invoke "f32.nearest" (f32.const 4.5)) (f32.const 4.0)) From c60d40c79820cf53dee3f46007495809e9c8700d Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Mon, 18 Apr 2016 15:09:34 -0700 Subject: [PATCH 3/4] Add tests for bugs reported in old hardware platforms. --- ml-proto/test/float_exprs.wast | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/ml-proto/test/float_exprs.wast b/ml-proto/test/float_exprs.wast index 34649315ab..1ed8a935b2 100644 --- a/ml-proto/test/float_exprs.wast +++ b/ml-proto/test/float_exprs.wast @@ -1218,3 +1218,32 @@ ) (assert_return (invoke "llvm_pr27153" (i32.const 33554434)) (f32.const 25165824.000000)) + +;; Test for bugs in old versions of historic IEEE 754 platforms as reported in: +;; +;; N. L. Schryer. 1981. A Test of a Computer's Floating-Point Arithmetic Unit. +;; Tech. Rep. Computer Science Technical Report 89, AT&T Bell Laboratories, Feb. +;; +;; specifically, the appendices describing IEEE systems with "The Past" sections +;; describing specific bugs. The 0 < 0 bug is omitted here due to being already +;; covered elsewhere. +(module + (func $thepast0 (param $a f64) (param $b f64) (param $c f64) (param $d f64) (result f64) + (f64.div (f64.mul (get_local $a) (get_local $b)) (f64.mul (get_local $c) (get_local $d))) + ) + (export "thepast0" $thepast0) + + (func $thepast1 (param $a f64) (param $b f64) (param $c f64) (result f64) + (f64.sub (f64.mul (get_local $a) (get_local $b)) (get_local $c)) + ) + (export "thepast1" $thepast1) + + (func $thepast2 (param $a f32) (param $b f32) (param $c f32) (result f32) + (f32.mul (f32.mul (get_local $a) (get_local $b)) (get_local $c)) + ) + (export "thepast2" $thepast2) +) + +(assert_return (invoke "thepast0" (f64.const 0x1p-1021) (f64.const 0x1.fffffffffffffp-1) (f64.const 0x1p1) (f64.const 0x1p-1)) (f64.const 0x1.fffffffffffffp-1022)) +(assert_return (invoke "thepast1" (f64.const 0x1p-54) (f64.const 0x1.fffffffffffffp-1) (f64.const 0x1p-54)) (f64.const -0x1p-107)) +(assert_return (invoke "thepast2" (f32.const 0x1p-125) (f32.const 0x1p-1) (f32.const 0x1p0)) (f32.const 0x1p-126)) From 5f830814e2cf81e4ed98339b71050ea923244548 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Mon, 18 Apr 2016 15:27:50 -0700 Subject: [PATCH 4/4] Test a case observed on some GPUs. --- ml-proto/test/float_exprs.wast | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ml-proto/test/float_exprs.wast b/ml-proto/test/float_exprs.wast index 1ed8a935b2..7307982c0e 100644 --- a/ml-proto/test/float_exprs.wast +++ b/ml-proto/test/float_exprs.wast @@ -1247,3 +1247,15 @@ (assert_return (invoke "thepast0" (f64.const 0x1p-1021) (f64.const 0x1.fffffffffffffp-1) (f64.const 0x1p1) (f64.const 0x1p-1)) (f64.const 0x1.fffffffffffffp-1022)) (assert_return (invoke "thepast1" (f64.const 0x1p-54) (f64.const 0x1.fffffffffffffp-1) (f64.const 0x1p-54)) (f64.const -0x1p-107)) (assert_return (invoke "thepast2" (f32.const 0x1p-125) (f32.const 0x1p-1) (f32.const 0x1p0)) (f32.const 0x1p-126)) + +;; Test for floating point tolerances observed in some GPUs. +;; https://community.amd.com/thread/145582 + +(module + (func $inverse (param $x f32) (result f32) + (f32.div (f32.const 1.0) (get_local $x)) + ) + (export "inverse" $inverse) +) + +(assert_return (invoke "inverse" (f32.const 96.0)) (f32.const 0x1.555556p-7))