From 5fa73c6193c0054a79b093f41ca7e82cbb9afbf9 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 27 Apr 2016 07:13:46 -0700 Subject: [PATCH 01/31] Test more floating-point almost-identities. --- ml-proto/test/float_exprs.wast | 42 ++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/ml-proto/test/float_exprs.wast b/ml-proto/test/float_exprs.wast index 7307982c0e..83769ab03e 100644 --- a/ml-proto/test/float_exprs.wast +++ b/ml-proto/test/float_exprs.wast @@ -39,6 +39,7 @@ (assert_return (invoke "f64.no_fma" (f64.const 0x1.7e2c44058a799p+52) (f64.const 0x1.c73b71765b8b2p+685) (f64.const -0x1.16c641df0b108p+690)) (f64.const 0x1.53ccb53de0bd1p+738)) ;; Test that x+0.0 is not folded to x. +;; See IEEE 754-2008 10.4 "Literal meaning and value-changing optimizations". (module (func $f32.no_fold_add_zero (param $x f32) (result f32) @@ -52,6 +53,8 @@ (assert_return (invoke "f32.no_fold_add_zero" (f32.const -0.0)) (f32.const 0.0)) (assert_return (invoke "f64.no_fold_add_zero" (f64.const -0.0)) (f64.const 0.0)) +(assert_return (invoke "f32.no_fold_add_zero" (f32.const nan:0x200000)) (f32.const nan:0x600000)) +(assert_return (invoke "f64.no_fold_add_zero" (f64.const nan:0x4000000000000)) (f64.const nan:0xc000000000000)) ;; Test that 0.0 - x is not folded to -x. @@ -70,6 +73,21 @@ (assert_return (invoke "f32.no_fold_zero_sub" (f32.const nan:0x200000)) (f32.const nan:0x600000)) (assert_return (invoke "f64.no_fold_zero_sub" (f64.const nan:0x4000000000000)) (f64.const nan:0xc000000000000)) +;; Test that x - 0.0 is not folded to x. + +(module + (func $f32.no_fold_sub_zero (param $x f32) (result f32) + (f32.sub (get_local $x) (f32.const 0.0))) + (export "f32.no_fold_sub_zero" $f32.no_fold_sub_zero) + + (func $f64.no_fold_sub_zero (param $x f64) (result f64) + (f64.sub (get_local $x) (f64.const 0.0))) + (export "f64.no_fold_sub_zero" $f64.no_fold_sub_zero) +) + +(assert_return (invoke "f32.no_fold_sub_zero" (f32.const nan:0x200000)) (f32.const nan:0x600000)) +(assert_return (invoke "f64.no_fold_sub_zero" (f64.const nan:0x4000000000000)) (f64.const nan:0xc000000000000)) + ;; Test that x*0.0 is not folded to 0.0. (module @@ -85,9 +103,27 @@ (assert_return (invoke "f32.no_fold_mul_zero" (f32.const -0.0)) (f32.const -0.0)) (assert_return (invoke "f32.no_fold_mul_zero" (f32.const -1.0)) (f32.const -0.0)) (assert_return (invoke "f32.no_fold_mul_zero" (f32.const -2.0)) (f32.const -0.0)) +(assert_return (invoke "f32.no_fold_mul_zero" (f32.const nan:0x200000)) (f32.const nan:0x600000)) (assert_return (invoke "f64.no_fold_mul_zero" (f64.const -0.0)) (f64.const -0.0)) (assert_return (invoke "f64.no_fold_mul_zero" (f64.const -1.0)) (f64.const -0.0)) (assert_return (invoke "f64.no_fold_mul_zero" (f64.const -2.0)) (f64.const -0.0)) +(assert_return (invoke "f64.no_fold_mul_zero" (f64.const nan:0x4000000000000)) (f64.const nan:0xc000000000000)) + +;; Test that x*1.0 is not folded to x. +;; See IEEE 754-2008 10.4 "Literal meaning and value-changing optimizations". + +(module + (func $f32.no_fold_mul_one (param $x f32) (result f32) + (f32.mul (get_local $x) (f32.const 1.0))) + (export "f32.no_fold_mul_one" $f32.no_fold_mul_one) + + (func $f64.no_fold_mul_one (param $x f64) (result f64) + (f64.mul (get_local $x) (f64.const 1.0))) + (export "f64.no_fold_mul_one" $f64.no_fold_mul_one) +) + +(assert_return (invoke "f32.no_fold_mul_one" (f32.const nan:0x200000)) (f32.const nan:0x600000)) +(assert_return (invoke "f64.no_fold_mul_one" (f64.const nan:0x4000000000000)) (f64.const nan:0xc000000000000)) ;; Test that 0.0/x is not folded to 0.0. @@ -104,9 +140,11 @@ (assert_return_nan (invoke "f32.no_fold_zero_div" (f32.const 0.0))) (assert_return_nan (invoke "f32.no_fold_zero_div" (f32.const -0.0))) (assert_return (invoke "f32.no_fold_zero_div" (f32.const nan)) (f32.const nan)) +(assert_return (invoke "f32.no_fold_zero_div" (f32.const nan:0x200000)) (f32.const nan:0x600000)) (assert_return_nan (invoke "f64.no_fold_zero_div" (f64.const 0.0))) (assert_return_nan (invoke "f64.no_fold_zero_div" (f64.const -0.0))) (assert_return (invoke "f64.no_fold_zero_div" (f64.const nan)) (f64.const nan)) +(assert_return (invoke "f64.no_fold_zero_div" (f64.const nan:0x4000000000000)) (f64.const nan:0xc000000000000)) ;; Test that x/1.0 is not folded to x. @@ -394,6 +432,7 @@ (assert_return (invoke "f32.no_fold_div_0" (f32.const -infinity)) (f32.const -infinity)) (assert_return_nan (invoke "f32.no_fold_div_0" (f32.const 0))) (assert_return_nan (invoke "f32.no_fold_div_0" (f32.const -0))) +(assert_return (invoke "f32.no_fold_div_0" (f32.const nan:0x200000)) (f32.const nan:0x600000)) (assert_return (invoke "f32.no_fold_div_0" (f32.const nan)) (f32.const nan)) (assert_return (invoke "f64.no_fold_div_0" (f64.const 1.0)) (f64.const infinity)) (assert_return (invoke "f64.no_fold_div_0" (f64.const -1.0)) (f64.const -infinity)) @@ -402,6 +441,7 @@ (assert_return_nan (invoke "f64.no_fold_div_0" (f64.const 0))) (assert_return_nan (invoke "f64.no_fold_div_0" (f64.const -0))) (assert_return (invoke "f64.no_fold_div_0" (f64.const nan)) (f64.const nan)) +(assert_return (invoke "f64.no_fold_div_0" (f64.const nan:0x4000000000000)) (f64.const nan:0xc000000000000)) ;; Test that x/-0 is not folded away. @@ -421,6 +461,7 @@ (assert_return (invoke "f32.no_fold_div_neg0" (f32.const -infinity)) (f32.const infinity)) (assert_return_nan (invoke "f32.no_fold_div_neg0" (f32.const 0))) (assert_return_nan (invoke "f32.no_fold_div_neg0" (f32.const -0))) +(assert_return (invoke "f32.no_fold_div_neg0" (f32.const nan:0x200000)) (f32.const nan:0x600000)) (assert_return (invoke "f32.no_fold_div_neg0" (f32.const nan)) (f32.const nan)) (assert_return (invoke "f64.no_fold_div_neg0" (f64.const 1.0)) (f64.const -infinity)) (assert_return (invoke "f64.no_fold_div_neg0" (f64.const -1.0)) (f64.const infinity)) @@ -429,6 +470,7 @@ (assert_return_nan (invoke "f64.no_fold_div_neg0" (f64.const 0))) (assert_return_nan (invoke "f64.no_fold_div_neg0" (f64.const -0))) (assert_return (invoke "f64.no_fold_div_neg0" (f64.const nan)) (f64.const nan)) +(assert_return (invoke "f64.no_fold_div_neg0" (f64.const nan:0x4000000000000)) (f64.const nan:0xc000000000000)) ;; Test that sqrt(x*x+y*y) is not folded to hypot. From ad06659a68ed126b16fe1a2d336f345062e48812 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 27 Apr 2016 07:13:52 -0700 Subject: [PATCH 02/31] Convert several inexact floating-point literals to hexadecimal form. --- ml-proto/test/conversions.wast | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/ml-proto/test/conversions.wast b/ml-proto/test/conversions.wast index 9711552a9c..0fe93e6120 100644 --- a/ml-proto/test/conversions.wast +++ b/ml-proto/test/conversions.wast @@ -107,10 +107,10 @@ (assert_return (invoke "i32.trunc_s_f32" (f32.const 0x1p-149)) (i32.const 0)) (assert_return (invoke "i32.trunc_s_f32" (f32.const -0x1p-149)) (i32.const 0)) (assert_return (invoke "i32.trunc_s_f32" (f32.const 1.0)) (i32.const 1)) -(assert_return (invoke "i32.trunc_s_f32" (f32.const 1.1)) (i32.const 1)) +(assert_return (invoke "i32.trunc_s_f32" (f32.const 0x1.19999ap+0)) (i32.const 1)) (assert_return (invoke "i32.trunc_s_f32" (f32.const 1.5)) (i32.const 1)) (assert_return (invoke "i32.trunc_s_f32" (f32.const -1.0)) (i32.const -1)) -(assert_return (invoke "i32.trunc_s_f32" (f32.const -1.1)) (i32.const -1)) +(assert_return (invoke "i32.trunc_s_f32" (f32.const -0x1.19999ap+0)) (i32.const -1)) (assert_return (invoke "i32.trunc_s_f32" (f32.const -1.5)) (i32.const -1)) (assert_return (invoke "i32.trunc_s_f32" (f32.const -1.9)) (i32.const -1)) (assert_return (invoke "i32.trunc_s_f32" (f32.const -2.0)) (i32.const -2)) @@ -127,13 +127,13 @@ (assert_return (invoke "i32.trunc_u_f32" (f32.const 0x1p-149)) (i32.const 0)) (assert_return (invoke "i32.trunc_u_f32" (f32.const -0x1p-149)) (i32.const 0)) (assert_return (invoke "i32.trunc_u_f32" (f32.const 1.0)) (i32.const 1)) -(assert_return (invoke "i32.trunc_u_f32" (f32.const 1.1)) (i32.const 1)) +(assert_return (invoke "i32.trunc_u_f32" (f32.const 0x1.19999ap+0)) (i32.const 1)) (assert_return (invoke "i32.trunc_u_f32" (f32.const 1.5)) (i32.const 1)) (assert_return (invoke "i32.trunc_u_f32" (f32.const 1.9)) (i32.const 1)) (assert_return (invoke "i32.trunc_u_f32" (f32.const 2.0)) (i32.const 2)) (assert_return (invoke "i32.trunc_u_f32" (f32.const 2147483648)) (i32.const -2147483648)) ;; 0x1.00000p+31 -> 8000 0000 (assert_return (invoke "i32.trunc_u_f32" (f32.const 4294967040.0)) (i32.const -256)) -(assert_return (invoke "i32.trunc_u_f32" (f32.const -0.9)) (i32.const 0)) +(assert_return (invoke "i32.trunc_u_f32" (f32.const -0x1.ccccccp-1)) (i32.const 0)) (assert_trap (invoke "i32.trunc_u_f32" (f32.const 4294967296.0)) "integer overflow") (assert_trap (invoke "i32.trunc_u_f32" (f32.const -1.0)) "integer overflow") (assert_trap (invoke "i32.trunc_u_f32" (f32.const infinity)) "integer overflow") @@ -145,10 +145,10 @@ (assert_return (invoke "i32.trunc_s_f64" (f64.const 0x0.0000000000001p-1022)) (i32.const 0)) (assert_return (invoke "i32.trunc_s_f64" (f64.const -0x0.0000000000001p-1022)) (i32.const 0)) (assert_return (invoke "i32.trunc_s_f64" (f64.const 1.0)) (i32.const 1)) -(assert_return (invoke "i32.trunc_s_f64" (f64.const 1.1)) (i32.const 1)) +(assert_return (invoke "i32.trunc_s_f64" (f64.const 0x1.199999999999ap+0)) (i32.const 1)) (assert_return (invoke "i32.trunc_s_f64" (f64.const 1.5)) (i32.const 1)) (assert_return (invoke "i32.trunc_s_f64" (f64.const -1.0)) (i32.const -1)) -(assert_return (invoke "i32.trunc_s_f64" (f64.const -1.1)) (i32.const -1)) +(assert_return (invoke "i32.trunc_s_f64" (f64.const -0x1.199999999999ap+0)) (i32.const -1)) (assert_return (invoke "i32.trunc_s_f64" (f64.const -1.5)) (i32.const -1)) (assert_return (invoke "i32.trunc_s_f64" (f64.const -1.9)) (i32.const -1)) (assert_return (invoke "i32.trunc_s_f64" (f64.const -2.0)) (i32.const -2)) @@ -165,13 +165,13 @@ (assert_return (invoke "i32.trunc_u_f64" (f64.const 0x0.0000000000001p-1022)) (i32.const 0)) (assert_return (invoke "i32.trunc_u_f64" (f64.const -0x0.0000000000001p-1022)) (i32.const 0)) (assert_return (invoke "i32.trunc_u_f64" (f64.const 1.0)) (i32.const 1)) -(assert_return (invoke "i32.trunc_u_f64" (f64.const 1.1)) (i32.const 1)) +(assert_return (invoke "i32.trunc_u_f64" (f64.const 0x1.199999999999ap+0)) (i32.const 1)) (assert_return (invoke "i32.trunc_u_f64" (f64.const 1.5)) (i32.const 1)) (assert_return (invoke "i32.trunc_u_f64" (f64.const 1.9)) (i32.const 1)) (assert_return (invoke "i32.trunc_u_f64" (f64.const 2.0)) (i32.const 2)) (assert_return (invoke "i32.trunc_u_f64" (f64.const 2147483648)) (i32.const -2147483648)) ;; 0x1.00000p+31 -> 8000 0000 (assert_return (invoke "i32.trunc_u_f64" (f64.const 4294967295.0)) (i32.const -1)) -(assert_return (invoke "i32.trunc_u_f64" (f64.const -0.9)) (i32.const 0)) +(assert_return (invoke "i32.trunc_u_f64" (f64.const -0x1.ccccccccccccdp-1)) (i32.const 0)) (assert_return (invoke "i32.trunc_u_f64" (f64.const 1e8)) (i32.const 100000000)) (assert_trap (invoke "i32.trunc_u_f64" (f64.const 4294967296.0)) "integer overflow") (assert_trap (invoke "i32.trunc_u_f64" (f64.const -1.0)) "integer overflow") @@ -187,10 +187,10 @@ (assert_return (invoke "i64.trunc_s_f32" (f32.const 0x1p-149)) (i64.const 0)) (assert_return (invoke "i64.trunc_s_f32" (f32.const -0x1p-149)) (i64.const 0)) (assert_return (invoke "i64.trunc_s_f32" (f32.const 1.0)) (i64.const 1)) -(assert_return (invoke "i64.trunc_s_f32" (f32.const 1.1)) (i64.const 1)) +(assert_return (invoke "i64.trunc_s_f32" (f32.const 0x1.19999ap+0)) (i64.const 1)) (assert_return (invoke "i64.trunc_s_f32" (f32.const 1.5)) (i64.const 1)) (assert_return (invoke "i64.trunc_s_f32" (f32.const -1.0)) (i64.const -1)) -(assert_return (invoke "i64.trunc_s_f32" (f32.const -1.1)) (i64.const -1)) +(assert_return (invoke "i64.trunc_s_f32" (f32.const -0x1.19999ap+0)) (i64.const -1)) (assert_return (invoke "i64.trunc_s_f32" (f32.const -1.5)) (i64.const -1)) (assert_return (invoke "i64.trunc_s_f32" (f32.const -1.9)) (i64.const -1)) (assert_return (invoke "i64.trunc_s_f32" (f32.const -2.0)) (i64.const -2)) @@ -209,11 +209,11 @@ (assert_return (invoke "i64.trunc_u_f32" (f32.const 0x1p-149)) (i64.const 0)) (assert_return (invoke "i64.trunc_u_f32" (f32.const -0x1p-149)) (i64.const 0)) (assert_return (invoke "i64.trunc_u_f32" (f32.const 1.0)) (i64.const 1)) -(assert_return (invoke "i64.trunc_u_f32" (f32.const 1.1)) (i64.const 1)) +(assert_return (invoke "i64.trunc_u_f32" (f32.const 0x1.19999ap+0)) (i64.const 1)) (assert_return (invoke "i64.trunc_u_f32" (f32.const 1.5)) (i64.const 1)) (assert_return (invoke "i64.trunc_u_f32" (f32.const 4294967296)) (i64.const 4294967296)) (assert_return (invoke "i64.trunc_u_f32" (f32.const 18446742974197923840.0)) (i64.const -1099511627776)) -(assert_return (invoke "i64.trunc_u_f32" (f32.const -0.9)) (i64.const 0)) +(assert_return (invoke "i64.trunc_u_f32" (f32.const -0x1.ccccccp-1)) (i64.const 0)) (assert_trap (invoke "i64.trunc_u_f32" (f32.const 18446744073709551616.0)) "integer overflow") (assert_trap (invoke "i64.trunc_u_f32" (f32.const -1.0)) "integer overflow") (assert_trap (invoke "i64.trunc_u_f32" (f32.const infinity)) "integer overflow") @@ -225,10 +225,10 @@ (assert_return (invoke "i64.trunc_s_f64" (f64.const 0x0.0000000000001p-1022)) (i64.const 0)) (assert_return (invoke "i64.trunc_s_f64" (f64.const -0x0.0000000000001p-1022)) (i64.const 0)) (assert_return (invoke "i64.trunc_s_f64" (f64.const 1.0)) (i64.const 1)) -(assert_return (invoke "i64.trunc_s_f64" (f64.const 1.1)) (i64.const 1)) +(assert_return (invoke "i64.trunc_s_f64" (f64.const 0x1.199999999999ap+0)) (i64.const 1)) (assert_return (invoke "i64.trunc_s_f64" (f64.const 1.5)) (i64.const 1)) (assert_return (invoke "i64.trunc_s_f64" (f64.const -1.0)) (i64.const -1)) -(assert_return (invoke "i64.trunc_s_f64" (f64.const -1.1)) (i64.const -1)) +(assert_return (invoke "i64.trunc_s_f64" (f64.const -0x1.199999999999ap+0)) (i64.const -1)) (assert_return (invoke "i64.trunc_s_f64" (f64.const -1.5)) (i64.const -1)) (assert_return (invoke "i64.trunc_s_f64" (f64.const -1.9)) (i64.const -1)) (assert_return (invoke "i64.trunc_s_f64" (f64.const -2.0)) (i64.const -2)) @@ -247,12 +247,12 @@ (assert_return (invoke "i64.trunc_u_f64" (f64.const 0x0.0000000000001p-1022)) (i64.const 0)) (assert_return (invoke "i64.trunc_u_f64" (f64.const -0x0.0000000000001p-1022)) (i64.const 0)) (assert_return (invoke "i64.trunc_u_f64" (f64.const 1.0)) (i64.const 1)) -(assert_return (invoke "i64.trunc_u_f64" (f64.const 1.1)) (i64.const 1)) +(assert_return (invoke "i64.trunc_u_f64" (f64.const 0x1.199999999999ap+0)) (i64.const 1)) (assert_return (invoke "i64.trunc_u_f64" (f64.const 1.5)) (i64.const 1)) (assert_return (invoke "i64.trunc_u_f64" (f64.const 4294967295)) (i64.const 0xffffffff)) (assert_return (invoke "i64.trunc_u_f64" (f64.const 4294967296)) (i64.const 0x100000000)) (assert_return (invoke "i64.trunc_u_f64" (f64.const 18446744073709549568.0)) (i64.const -2048)) -(assert_return (invoke "i64.trunc_u_f64" (f64.const -0.9)) (i64.const 0)) +(assert_return (invoke "i64.trunc_u_f64" (f64.const -0x1.ccccccccccccdp-1)) (i64.const 0)) (assert_return (invoke "i64.trunc_u_f64" (f64.const 1e8)) (i64.const 100000000)) (assert_return (invoke "i64.trunc_u_f64" (f64.const 1e16)) (i64.const 10000000000000000)) (assert_return (invoke "i64.trunc_u_f64" (f64.const 9223372036854775808)) (i64.const -9223372036854775808)) From fa5a8b6d298d5acac1290023b3b503384a6df927 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 27 Apr 2016 07:13:54 -0700 Subject: [PATCH 03/31] Add a testcase based on LLVM PR27036. --- ml-proto/test/float_exprs.wast | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/ml-proto/test/float_exprs.wast b/ml-proto/test/float_exprs.wast index 83769ab03e..d7bffb13aa 100644 --- a/ml-proto/test/float_exprs.wast +++ b/ml-proto/test/float_exprs.wast @@ -1261,6 +1261,19 @@ (assert_return (invoke "llvm_pr27153" (i32.const 33554434)) (f32.const 25165824.000000)) +;; Test that (float)x + (float)y is not optimzied to (float)(x + y) when unsafe. +;; https://llvm.org/bugs/show_bug.cgi?id=27036 + +(module + (func $llvm_pr27036 (param $x i32) (param $y i32) (result f32) + (f32.add (f32.convert_s/i32 (i32.or (get_local $x) (i32.const -25034805))) + (f32.convert_s/i32 (i32.and (get_local $y) (i32.const 14942208)))) + ) + (export "llvm_pr27936" $llvm_pr27036) +) + +(assert_return (invoke "llvm_pr27936" (i32.const -25034805) (i32.const 14942208)) (f32.const -0x1.340068p+23)) + ;; 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. From d337029a0378de807d863a48230515596b46bf8d Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 27 Apr 2016 07:13:56 -0700 Subject: [PATCH 04/31] Test for incorrect rounding on sqrt(4.0). --- ml-proto/test/float_exprs.wast | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/ml-proto/test/float_exprs.wast b/ml-proto/test/float_exprs.wast index d7bffb13aa..40a64cceff 100644 --- a/ml-proto/test/float_exprs.wast +++ b/ml-proto/test/float_exprs.wast @@ -1314,3 +1314,21 @@ ) (assert_return (invoke "inverse" (f32.const 96.0)) (f32.const 0x1.555556p-7)) + +;; Test for incorrect rounding on sqrt(4.0). +;; http://www.askvg.com/microsoft-windows-calculator-bug/ + +(module + (func $f32_sqrt_minus_2 (param $x f32) (result f32) + (f32.sub (f32.sqrt (get_local $x)) (f32.const 2.0)) + ) + (export "f32_sqrt_minus_2" $f32_sqrt_minus_2) + + (func $f64_sqrt_minus_2 (param $x f64) (result f64) + (f64.sub (f64.sqrt (get_local $x)) (f64.const 2.0)) + ) + (export "f64_sqrt_minus_2" $f64_sqrt_minus_2) +) + +(assert_return (invoke "f32_sqrt_minus_2" (f32.const 4.0)) (f32.const 0.0)) +(assert_return (invoke "f64_sqrt_minus_2" (f64.const 4.0)) (f64.const 0.0)) From 94ddb530c76ebbe1abf255fb807500787f4b79c5 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 27 Apr 2016 07:13:58 -0700 Subject: [PATCH 05/31] Test another notable x87 sqrt case. --- ml-proto/test/float_misc.wast | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ml-proto/test/float_misc.wast b/ml-proto/test/float_misc.wast index 32ff6cba66..e161c0c27a 100644 --- a/ml-proto/test/float_misc.wast +++ b/ml-proto/test/float_misc.wast @@ -415,6 +415,10 @@ (assert_return (invoke "f64.sqrt" (f64.const 0x1.518c8e68cb753p-37)) (f64.const 0x1.9fb8ef1ad5bfdp-19)) (assert_return (invoke "f64.sqrt" (f64.const 0x1.86d8b6518078ep-370)) (f64.const 0x1.3c5142a48fcadp-185)) +;; Test another sqrt case on x87. +;; https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52593 +(assert_return (invoke "f64.sqrt" (f64.const 0x1.fffffffffffffp-1)) (f64.const 0x1.fffffffffffffp-1)) + ;; Test for bugs found in an early RISC-V implementation. ;; https://github.com/riscv/riscv-tests/pull/8 (assert_return (invoke "f64.sqrt" (f64.const 0x1.56p+7)) (f64.const 0x1.a2744ce9674f5p+3)) From 20825b0fe250e5f03f113b1c97fc88023bcf7f27 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 27 Apr 2016 07:13:59 -0700 Subject: [PATCH 06/31] Test 1/(1/x). --- ml-proto/test/float_exprs.wast | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/ml-proto/test/float_exprs.wast b/ml-proto/test/float_exprs.wast index 40a64cceff..93b7a8ae3d 100644 --- a/ml-proto/test/float_exprs.wast +++ b/ml-proto/test/float_exprs.wast @@ -1332,3 +1332,27 @@ (assert_return (invoke "f32_sqrt_minus_2" (f32.const 4.0)) (f32.const 0.0)) (assert_return (invoke "f64_sqrt_minus_2" (f64.const 4.0)) (f64.const 0.0)) + +;; Test that 1.0 / (1.0 / x) is not optimized to x. + +(module + (func $f32.no_fold_recip_recip (param $x f32) (result f32) + (f32.div (f32.const 1.0) (f32.div (f32.const 1.0) (get_local $x)))) + (export "f32.no_fold_recip_recip" $f32.no_fold_recip_recip) + + (func $f64.no_fold_recip_recip (param $x f64) (result f64) + (f64.div (f64.const 1.0) (f64.div (f64.const 1.0) (get_local $x)))) + (export "f64.no_fold_recip_recip" $f64.no_fold_recip_recip) +) + +(assert_return (invoke "f32.no_fold_recip_recip" (f32.const -0x1.e8bf18p+65)) (f32.const -0x1.e8bf16p+65)) +(assert_return (invoke "f32.no_fold_recip_recip" (f32.const 0x1.e24248p-77)) (f32.const 0x1.e24246p-77)) +(assert_return (invoke "f32.no_fold_recip_recip" (f32.const 0x1.caf0e8p-64)) (f32.const 0x1.caf0eap-64)) +(assert_return (invoke "f32.no_fold_recip_recip" (f32.const -0x1.e66982p+4)) (f32.const -0x1.e66984p+4)) +(assert_return (invoke "f32.no_fold_recip_recip" (f32.const 0x1.f99916p+70)) (f32.const 0x1.f99914p+70)) + +(assert_return (invoke "f64.no_fold_recip_recip" (f64.const -0x1.d81248dda63dp+148)) (f64.const -0x1.d81248dda63d1p+148)) +(assert_return (invoke "f64.no_fold_recip_recip" (f64.const -0x1.f4750312039e3p+66)) (f64.const -0x1.f4750312039e2p+66)) +(assert_return (invoke "f64.no_fold_recip_recip" (f64.const 0x1.fa50630eec7f6p+166)) (f64.const 0x1.fa50630eec7f5p+166)) +(assert_return (invoke "f64.no_fold_recip_recip" (f64.const 0x1.db0598617ba92p-686)) (f64.const 0x1.db0598617ba91p-686)) +(assert_return (invoke "f64.no_fold_recip_recip" (f64.const 0x1.85f1638a0c82bp+902)) (f64.const 0x1.85f1638a0c82ap+902)) From 48b085ec998e2095f9bdda4458874c7b1b86af46 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 27 Apr 2016 07:14:01 -0700 Subject: [PATCH 07/31] Test algebraic factoring reversal. --- ml-proto/test/float_exprs.wast | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/ml-proto/test/float_exprs.wast b/ml-proto/test/float_exprs.wast index 93b7a8ae3d..0ad543b9c5 100644 --- a/ml-proto/test/float_exprs.wast +++ b/ml-proto/test/float_exprs.wast @@ -1356,3 +1356,29 @@ (assert_return (invoke "f64.no_fold_recip_recip" (f64.const 0x1.fa50630eec7f6p+166)) (f64.const 0x1.fa50630eec7f5p+166)) (assert_return (invoke "f64.no_fold_recip_recip" (f64.const 0x1.db0598617ba92p-686)) (f64.const 0x1.db0598617ba91p-686)) (assert_return (invoke "f64.no_fold_recip_recip" (f64.const 0x1.85f1638a0c82bp+902)) (f64.const 0x1.85f1638a0c82ap+902)) + +;; Test that (x+y) * (x-y) is not optimized to x*x - y*y. + +(module + (func $f32.no_algebraic_factoring (param $x f32) (param $y f32) (result f32) + (f32.mul (f32.add (get_local $x) (get_local $y)) + (f32.sub (get_local $x) (get_local $y)))) + (export "f32.no_algebraic_factoring" $f32.no_algebraic_factoring) + + (func $f64.no_algebraic_factoring (param $x f64) (param $y f64) (result f64) + (f64.mul (f64.add (get_local $x) (get_local $y)) + (f64.sub (get_local $x) (get_local $y)))) + (export "f64.no_algebraic_factoring" $f64.no_algebraic_factoring) +) + +(assert_return (invoke "f32.no_algebraic_factoring" (f32.const -0x1.ef678ep-55) (f32.const 0x1.c160b8p-54)) (f32.const -0x1.129402p-107)) +(assert_return (invoke "f32.no_algebraic_factoring" (f32.const -0x1.2d76bcp+24) (f32.const 0x1.f4089cp+24)) (f32.const -0x1.36d89ap+49)) +(assert_return (invoke "f32.no_algebraic_factoring" (f32.const 0x1.7ca2b2p+45) (f32.const -0x1.08513cp+47)) (f32.const -0x1.db10dep+93)) +(assert_return (invoke "f32.no_algebraic_factoring" (f32.const 0x1.7d5e3p+17) (f32.const -0x1.c783b4p+7)) (f32.const 0x1.1c10a6p+35)) +(assert_return (invoke "f32.no_algebraic_factoring" (f32.const -0x1.daf96p+7) (f32.const -0x1.dac6bp+19)) (f32.const -0x1.b8422ep+39)) + +(assert_return (invoke "f64.no_algebraic_factoring" (f64.const 0x1.e17c0a02ac6b5p-476) (f64.const 0x1.e8f13f1fcdc14p-463)) (f64.const -0x1.d2ec518f62863p-925)) +(assert_return (invoke "f64.no_algebraic_factoring" (f64.const 0x1.971b55a57e3a3p-377) (f64.const 0x1.edeb4233c1b27p-399)) (f64.const 0x1.43b3f69fb258bp-753)) +(assert_return (invoke "f64.no_algebraic_factoring" (f64.const -0x1.c3b9dc02472fap-378) (f64.const -0x1.74e9faebaff14p-369)) (f64.const -0x1.0f9c07e8caa25p-737)) +(assert_return (invoke "f64.no_algebraic_factoring" (f64.const -0x1.afaf4688ed019p+179) (f64.const 0x1.b07171cb49e94p+188)) (f64.const -0x1.6d3f2e2bebcf7p+377)) +(assert_return (invoke "f64.no_algebraic_factoring" (f64.const 0x1.4377a98948f12p+114) (f64.const -0x1.500c05bd24c97p+90)) (f64.const 0x1.98b72dbf7bf72p+228)) From 65f1ef078104cbce3fb68d8ef5f25ec9e13ef665 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 27 Apr 2016 07:14:02 -0700 Subject: [PATCH 08/31] Test algebraic factoring. --- ml-proto/test/float_exprs.wast | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/ml-proto/test/float_exprs.wast b/ml-proto/test/float_exprs.wast index 0ad543b9c5..2f07c4b4e7 100644 --- a/ml-proto/test/float_exprs.wast +++ b/ml-proto/test/float_exprs.wast @@ -1382,3 +1382,29 @@ (assert_return (invoke "f64.no_algebraic_factoring" (f64.const -0x1.c3b9dc02472fap-378) (f64.const -0x1.74e9faebaff14p-369)) (f64.const -0x1.0f9c07e8caa25p-737)) (assert_return (invoke "f64.no_algebraic_factoring" (f64.const -0x1.afaf4688ed019p+179) (f64.const 0x1.b07171cb49e94p+188)) (f64.const -0x1.6d3f2e2bebcf7p+377)) (assert_return (invoke "f64.no_algebraic_factoring" (f64.const 0x1.4377a98948f12p+114) (f64.const -0x1.500c05bd24c97p+90)) (f64.const 0x1.98b72dbf7bf72p+228)) + +;; Test that x*x - y*y is not optimized to (x+y) * (x-y). + +(module + (func $f32.no_algebraic_factoring (param $x f32) (param $y f32) (result f32) + (f32.sub (f32.mul (get_local $x) (get_local $x)) + (f32.mul (get_local $y) (get_local $y)))) + (export "f32.no_algebraic_factoring" $f32.no_algebraic_factoring) + + (func $f64.no_algebraic_factoring (param $x f64) (param $y f64) (result f64) + (f64.sub (f64.mul (get_local $x) (get_local $x)) + (f64.mul (get_local $y) (get_local $y)))) + (export "f64.no_algebraic_factoring" $f64.no_algebraic_factoring) +) + +(assert_return (invoke "f32.no_algebraic_factoring" (f32.const 0x1.8e2c14p-46) (f32.const 0x1.bad59ap-39)) (f32.const -0x1.7efe5p-77)) +(assert_return (invoke "f32.no_algebraic_factoring" (f32.const -0x1.7ef192p+41) (f32.const -0x1.db184ap+33)) (f32.const 0x1.1e6932p+83)) +(assert_return (invoke "f32.no_algebraic_factoring" (f32.const 0x1.7eb458p-12) (f32.const -0x1.52c498p-13)) (f32.const 0x1.cc0bc6p-24)) +(assert_return (invoke "f32.no_algebraic_factoring" (f32.const 0x1.2675c6p-44) (f32.const -0x1.edd31ap-46)) (f32.const 0x1.17294cp-88)) +(assert_return (invoke "f32.no_algebraic_factoring" (f32.const 0x1.9a5f92p+51) (f32.const -0x1.2b0098p+52)) (f32.const -0x1.7189a6p+103)) + +(assert_return (invoke "f64.no_algebraic_factoring" (f64.const 0x1.749a128f18f69p+356) (f64.const -0x1.0bc97ee1354e1p+337)) (f64.const 0x1.0f28115518d74p+713)) +(assert_return (invoke "f64.no_algebraic_factoring" (f64.const -0x1.2dab01b2215eap+309) (f64.const -0x1.e12b288bff2bdp+331)) (f64.const -0x1.c4319ad25d201p+663)) +(assert_return (invoke "f64.no_algebraic_factoring" (f64.const 0x1.3ed898431e102p+42) (f64.const -0x1.c409183fa92e6p+39)) (f64.const 0x1.80a611103c71dp+84)) +(assert_return (invoke "f64.no_algebraic_factoring" (f64.const -0x1.be663e4c0e4b2p+182) (f64.const -0x1.da85703760d25p+166)) (f64.const 0x1.853434f1a2ffep+365)) +(assert_return (invoke "f64.no_algebraic_factoring" (f64.const -0x1.230e09952df1cp-236) (f64.const -0x1.fa2752adfadc9p-237)) (f64.const 0x1.42e43156bd1b8p-474)) From 24e98eabda8adb2134bc463ae20eeba50994f363 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 27 Apr 2016 07:14:04 -0700 Subject: [PATCH 09/31] Test plain and Kahan summation. --- ml-proto/test/float_exprs.wast | 73 ++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/ml-proto/test/float_exprs.wast b/ml-proto/test/float_exprs.wast index 2f07c4b4e7..1705566f53 100644 --- a/ml-proto/test/float_exprs.wast +++ b/ml-proto/test/float_exprs.wast @@ -1408,3 +1408,76 @@ (assert_return (invoke "f64.no_algebraic_factoring" (f64.const 0x1.3ed898431e102p+42) (f64.const -0x1.c409183fa92e6p+39)) (f64.const 0x1.80a611103c71dp+84)) (assert_return (invoke "f64.no_algebraic_factoring" (f64.const -0x1.be663e4c0e4b2p+182) (f64.const -0x1.da85703760d25p+166)) (f64.const 0x1.853434f1a2ffep+365)) (assert_return (invoke "f64.no_algebraic_factoring" (f64.const -0x1.230e09952df1cp-236) (f64.const -0x1.fa2752adfadc9p-237)) (f64.const 0x1.42e43156bd1b8p-474)) + +;; Test that plain summation is not reassociated, and that Kahan summation +;; isn't optimized into plain summation. + +(module + (memory 1 1 + (segment 0 "\c4\c5\57\24\a5\84\c8\0b\6d\b8\4b\2e\f2\76\17\1c\ca\4a\56\1e\1b\6e\71\22\5d\17\1e\6e\bf\cd\14\5c\c7\21\55\51\39\9c\1f\b2\51\f0\a3\93\d7\c1\2c\ae\7e\a8\28\3a\01\21\f4\0a\58\93\f8\42\77\9f\83\39\6a\5f\ba\f7\0a\d8\51\6a\34\ca\ad\c6\34\0e\d8\26\dc\4c\33\1c\ed\29\90\a8\78\0f\d1\ce\76\31\23\83\b8\35\e8\f2\44\b0\d3\a1\fc\bb\32\e1\b0\ba\69\44\09\d6\d9\7d\ff\2e\c0\5a\36\14\33\14\3e\a9\fa\87\6d\8b\bc\ce\9d\a7\fd\c4\e9\85\3f\dd\d7\e1\18\a6\50\26\72\6e\3f\73\0f\f8\12\93\23\34\61\76\12\48\c0\9b\05\93\eb\ac\86\de\94\3e\55\e8\8c\e8\dd\e4\fc\95\47\be\56\03\21\20\4c\e6\bf\7b\f6\7f\d5\ba\73\1c\c1\14\8f\c4\27\96\b3\bd\33\ff\78\41\5f\c0\5a\ce\f6\67\6e\73\9a\17\66\70\03\f8\ce\27\a3\52\b2\9f\3b\bf\fb\ae\ed\d3\5a\f8\37\57\f0\f5\6e\ef\b1\4d\70\3d\54\a7\01\9a\85\08\48\91\f5\9d\0c\60\87\5b\d9\54\1e\51\6d\88\8e\08\8c\a5\71\3a\56\08\67\46\8f\8f\13\2a\2c\ec\2c\1f\b4\62\2b\6f\41\0a\c4\65\42\a2\31\6b\2c\7d\3e\bb\75\ac\86\97\30\d9\48\cd\9a\1f\56\c4\c6\e4\12\c0\9d\fb\ee\02\8c\ce\1c\f2\1e\a1\78\23\db\c4\1e\49\03\d3\71\cc\08\50\c5\d8\5c\ed\d5\b5\65\ac\b5\c9\21\d2\c9\29\76\de\f0\30\1a\5b\3c\f2\3b\db\3a\39\82\3a\16\08\6f\a8\f1\be\69\69\99\71\a6\05\d3\14\93\2a\16\f2\2f\11\c7\7e\20\bb\91\44\ee\f8\e4\01\53\c0\b9\7f\f0\bf\f0\03\9c\6d\b1\df\a2\44\01\6d\6b\71\2b\5c\b3\21\19\46\5e\8f\db\91\d3\7c\78\6b\b7\12\00\8f\eb\bd\8a\f5\d4\2e\c4\c1\1e\df\73\63\59\47\49\03\0a\b7\cf\24\cf\9c\0e\44\7a\9e\14\fb\42\bf\9d\39\30\9e\a0\ab\2f\d1\ae\9e\6a\83\43\e3\55\7d\85\bf\63\8a\f8\96\10\1f\fe\6d\e7\22\1b\e1\69\46\8a\44\c8\c8\f9\0c\2b\19\07\a5\02\3e\f2\30\10\9a\85\8a\5f\ef\81\45\a0\77\b1\03\10\73\4b\ae\98\9d\47\bf\9a\2d\3a\d5\0f\03\66\e3\3d\53\d9\40\ce\1f\6f\32\2f\21\2b\23\21\6c\62\d4\a7\3e\a8\ce\28\31\2d\00\3d\67\5e\af\a0\cf\2e\d2\b9\6b\84\eb\69\08\3c\62\36\be\12\fd\36\7f\88\3e\ad\bc\0b\c0\41\c4\50\b6\e3\50\31\e8\ce\e2\96\65\55\9c\16\46\e6\b0\2d\3a\e8\81\05\b0\bf\34\f7\bc\10\1c\fb\cc\3c\f1\85\97\42\9f\eb\14\8d\3c\bf\d7\17\88\49\9d\8b\2b\b2\3a\83\d1\4f\04\9e\a1\0f\ad\08\9d\54\af\d1\82\c3\ec\32\2f\02\8f\05\21\2d\a2\b7\e4\f4\6f\2e\81\2b\0b\9c\fc\cb\fe\74\02\f9\db\f4\f3\ea\00\a8\ec\d1\99\74\26\dd\d6\34\d5\25\b1\46\dd\9c\aa\71\f5\60\b0\88\c8\e0\0b\59\5a\25\4f\29\66\f9\e3\2e\fe\e9\da\e5\18\4f\27\62\f4\ce\a4\21\95\74\c7\57\64\27\9a\4c\fd\54\7d\61\ce\c3\ac\87\46\9c\fa\ff\09\ca\79\97\67\24\74\ca\d4\21\83\26\25\19\12\37\64\19\e5\65\e0\74\75\8e\dd\c8\ef\74\c7\d8\21\2b\79\04\51\46\65\60\03\5d\fa\d8\f4\65\a4\9e\5d\23\da\d7\8a\92\80\a4\de\78\3c\f1\57\42\6d\cd\c9\2f\d5\a4\9e\ab\40\f4\cb\1b\d7\a3\ca\fc\eb\a7\01\b2\9a\69\4e\46\9b\18\4e\dd\79\a7\aa\a6\52\39\1e\ef\30\cc\9b\bd\5b\ee\4c\21\6d\30\00\72\b0\46\5f\08\cf\c5\b9\e0\3e\c2\b3\0c\dc\8e\64\de\19\42\79\cf\43\ea\43\5d\8e\88\f7\ab\15\dc\3f\c8\67\20\db\b8\64\b1\47\1f\de\f2\cb\3f\59\9f\d8\46\90\dc\ae\2f\22\f9\e2\31\89\d9\9c\1c\4c\d3\a9\4a\57\84\9c\9f\ea\2c\3c\ae\3c\c3\1e\8b\e5\4e\17\01\25\db\34\46\5f\15\ea\05\0c\7c\d9\45\8c\19\d0\73\8a\96\16\dd\44\f9\05\b7\5b\71\b0\e6\21\36\5f\75\89\91\73\75\ab\7d\ae\d3\73\ec\37\c6\ea\55\75\ef\ea\ab\8b\7b\11\dc\6d\1a\b2\6a\c4\25\cf\aa\e3\9f\49\49\89\cb\37\9b\0a\a7\01\60\70\dc\b7\c8\83\e1\42\f5\be\ad\62\94\ad\8d\a1") + ) + + (func $f32.kahan_sum (param $p i32) (param $n i32) (result f32) + (local $sum f32) + (local $c f32) + (local $t f32) + (loop $exit $top + (set_local $t (f32.sub (f32.sub (set_local $sum (f32.add (get_local $c) (set_local $t (f32.sub (f32.load (get_local $p)) (get_local $t))))) (get_local $c)) (get_local $t))) + (set_local $p (i32.add (get_local $p) (i32.const 4))) + (set_local $c (get_local $sum)) + (br_if $top (set_local $n (i32.add (get_local $n) (i32.const -1)))) + ) + (get_local $sum) + ) + (export "f32.kahan_sum" $f32.kahan_sum) + + (func $f32.plain_sum (param $p i32) (param $n i32) (result f32) + (local $sum f32) + (loop $exit $top + (set_local $sum (f32.add (get_local $sum) (f32.load (get_local $p)))) + (set_local $p (i32.add (get_local $p) (i32.const 4))) + (set_local $n (i32.add (get_local $n) (i32.const -1))) + (br_if $top (get_local $n)) + ) + (get_local $sum) + ) + (export "f32.plain_sum" $f32.plain_sum) +) + +(assert_return (invoke "f32.kahan_sum" (i32.const 0) (i32.const 256)) (f32.const -0x1.101a1ap+104)) +(assert_return (invoke "f32.plain_sum" (i32.const 0) (i32.const 256)) (f32.const -0x1.a0343ap+103)) + +(module + (memory 1 1 + (segment 0 "\13\05\84\42\5d\a2\2c\c6\43\db\55\a9\cd\da\55\e3\73\fc\58\d6\ba\d5\00\fd\83\35\42\88\8b\13\5d\38\4a\47\0d\72\73\a1\1a\ef\c4\45\17\57\d8\c9\46\e0\8d\6c\e1\37\70\c8\83\5b\55\5e\5a\2d\73\1e\56\c8\e1\6d\69\14\78\0a\8a\5a\64\3a\09\c7\a8\87\c5\f0\d3\5d\e6\03\fc\93\be\26\ca\d6\a9\91\60\bd\b0\ed\ae\f7\30\7e\92\3a\6f\a7\59\8e\aa\7d\bf\67\58\2a\54\f8\4e\fe\ed\35\58\a6\51\bf\42\e5\4b\66\27\24\6d\7f\42\2d\28\92\18\ec\08\ae\e7\55\da\b1\a6\65\a5\72\50\47\1b\b8\a9\54\d7\a6\06\5b\0f\42\58\83\8a\17\82\c6\10\43\a0\c0\2e\6d\bc\5a\85\53\72\7f\ad\44\bc\30\3c\55\b2\24\9a\74\3a\9e\e1\d8\0f\70\fc\a9\3a\cd\93\4b\ec\e3\7e\dd\5d\27\cd\f8\a0\9d\1c\11\c0\57\2e\fd\c8\13\32\cc\3a\1a\7d\a3\41\55\ed\c3\82\49\2a\04\1e\ef\73\b9\2e\2e\e3\5f\f4\df\e6\b2\33\0c\39\3f\6f\44\6a\03\c1\42\b9\fa\b1\c8\ed\a5\58\99\7f\ed\b4\72\9e\79\eb\fb\43\82\45\aa\bb\95\d2\ff\28\9e\f6\a1\ad\95\d6\55\95\0d\6f\60\11\c7\78\3e\49\f2\7e\48\f4\a2\71\d0\13\8e\b3\de\99\52\e3\45\74\ea\76\0e\1b\2a\c8\ee\14\01\c4\50\5b\36\3c\ef\ba\72\a2\a6\08\f8\7b\36\9d\f9\ef\0b\c7\56\2d\5c\f0\9d\5d\de\fc\b8\ad\0f\64\0e\97\15\32\26\c2\31\e6\05\1e\ef\cb\17\1b\6d\15\0b\74\5d\d3\2e\f8\6b\86\b4\ba\73\52\53\99\a9\76\20\45\c9\40\80\6b\14\ed\a1\fa\80\46\e6\26\d2\e6\98\c4\57\bf\c4\1c\a4\90\7a\36\94\14\ba\15\89\6e\e6\9c\37\8c\f4\de\12\22\5d\a1\79\50\67\0d\3d\7a\e9\d4\aa\2e\7f\2a\7a\30\3d\ea\5d\12\48\fe\e1\18\cd\a4\57\a2\87\3e\b6\9a\8b\db\da\9d\78\9c\cf\8d\b1\4f\90\b4\34\e0\9d\f6\ca\fe\4c\3b\78\6d\0a\5c\18\9f\61\b9\dd\b4\e0\0f\76\e0\1b\69\0d\5e\58\73\70\5e\0e\2d\a1\7d\ff\20\eb\91\34\92\ac\38\72\2a\1f\8e\71\2e\6a\f1\af\c7\27\70\d9\c4\57\f7\d2\3c\1d\b8\f0\f0\64\cf\dc\ae\be\a3\cc\3e\22\7d\4e\69\21\63\17\ed\03\02\54\9a\0f\50\4e\13\5a\35\a1\22\a4\df\86\c2\74\79\16\b8\69\69\a0\52\5d\11\64\bd\5b\93\fc\69\a0\f4\13\d0\81\51\dd\fa\0c\15\c3\7a\c9\62\7a\a9\1d\c9\e6\5a\b3\5b\97\02\3c\64\22\12\3c\22\90\64\2d\30\54\4c\b4\a1\22\09\57\22\5e\8e\38\2b\02\a8\ae\f6\be\0d\2b\f2\03\ad\fa\10\01\71\77\2a\30\02\95\f6\00\3e\d0\c4\8d\34\19\50\21\0a\bc\50\da\3c\30\d6\3a\31\94\8d\3a\fe\ef\14\57\9d\4b\93\00\96\24\0c\6f\fd\bc\23\76\02\6c\eb\52\72\80\11\7e\80\3a\13\12\38\1d\38\49\95\40\27\8a\44\7b\e8\dc\6d\8c\8c\8e\3c\b5\b3\18\0e\f6\08\1a\84\41\35\ff\8b\b8\93\40\ea\e1\51\1d\89\a5\8d\42\68\29\ea\2f\c1\7a\52\eb\90\5d\4d\d6\80\e3\d7\75\48\ce\ed\d3\01\1c\8d\5b\a5\94\0d\78\cf\f1\06\13\2f\98\02\a4\6d\2e\6c\f2\d5\74\29\89\4c\f9\03\f5\c7\18\ad\7a\f0\68\f8\5c\d6\59\87\6e\d6\3f\06\be\86\20\e3\41\91\22\f3\6e\8b\f0\68\1c\57\a7\fc\b0\7c\9e\99\0b\96\1a\89\5f\e6\0d\7c\08\51\a0\a2\67\9a\47\00\93\6b\f9\28\f0\68\db\62\f1\e0\65\2c\53\33\e0\a7\ca\11\42\30\f6\af\01\c1\65\3d\32\01\6f\ab\2e\be\d3\8b\be\14\c3\ff\ec\fb\f0\f9\c5\0c\05\6f\01\09\6b\e3\34\31\0c\1f\66\a6\42\bc\1a\87\49\16\16\8c\b0\90\0d\34\8c\0a\e1\09\5e\10\a4\6b\56\cc\f0\c9\bb\dc\b8\5c\ce\f6\cc\8d\75\7e\b3\07\88\04\2f\b4\5e\c9\e3\4a\23\73\19\62\6c\9a\03\76\44\86\9c\60\fc\db\72\8f\27\a0\dd\b3\c5\da\ff\f9\ec\6a\b1\7b\d3\cf\50\37\c9\7a\78\0c\e4\3a\b6\f5\e6\f4\98\6e\42\7d\35\73\8b\45\c0\56\97\cd\6d\ce\cf\ad\31\b3\c3\54\fa\ef\d5\c0\f4\6a\5f\54\e7\49\3e\33\0a\30\38\fd\d9\05\ff\a5\3f\57\46\14\b5\91\17\ca\6b\98\23\7a\65\b3\6c\02\b4\cc\79\5d\58\d8\b3\d5\94\ae\f4\6d\75\65\f7\92\bf\7e\47\4c\3c\ee\db\ac\f1\32\5d\fb\6f\41\1c\34\c8\83\4f\c2\58\01\be\05\3e\66\16\a6\04\6d\5d\4f\86\09\27\82\25\12\cd\3a\cd\ce\6b\bc\ca\ac\28\9b\ee\6a\25\86\9e\45\70\c6\d2\bd\3b\7d\42\e5\27\af\c7\1d\f4\81\c8\b3\76\8a\a8\36\a3\ae\2a\e6\18\e1\36\22\ad\f6\25\72\b0\39\8b\01\9a\22\7b\84\c3\2d\5f\72\a4\98\ac\15\70\e7\d4\18\e2\7d\d2\30\7c\33\08\cd\ca\c4\22\85\88\75\81\c6\4a\74\58\8d\e0\e8\ac\c5\ab\75\5a\f4\28\12\f0\18\45\52\f2\97\b2\93\41\6f\8d\7f\db\70\fb\a3\5d\1f\a7\8d\98\20\2b\22\9f\3a\01\b5\8b\1b\d2\cb\14\03\0e\14\14\d2\19\5a\1f\ce\5e\cd\81\79\15\01\ca\de\73\74\8c\56\20\9f\77\2d\25\16\f6\61\51\1d\a4\8e\9b\98\a5\c6\ec\a8\45\57\82\59\78\0d\90\b4\df\51\b0\c3\82\94\cc\b3\53\09\15\6d\96\6c\3a\40\47\b7\4a\7a\05\2f\a1\1e\8c\9d\a0\20\88\fb\52\b7\9f\f3\f3\bb\5f\e7\8a\61\a7\21\b1\ac\fa\09\aa\a4\6c\bc\24\80\ba\2a\e9\65\ff\70\ff\cc\fa\65\87\76\f3\c5\15\ce\cb\e8\42\31\00\0c\91\57\d9\e0\9d\35\54\24\ad\a4\d8\f9\08\67\63\c8\cf\81\dd\90\a2\d7\c4\07\4a\e6\10\6f\67\e7\27\d4\23\59\18\f2\a8\9d\5f\d8\94\30\aa\54\86\4f\87\9d\82\b5\26\ca\a6\96\bf\cf\55\f9\9d\37\01\19\48\43\c5\94\6c\f3\74\97\58\4c\3c\9d\08\e8\04\c2\58\30\76\e1\a0\f8\ea\e9\c5\ae\cf\78\9e\a9\0c\ac\b3\44\42\e0\bc\5d\1b\9c\49\58\4a\1c\19\49\c1\3a\ea\f5\eb\3b\81\a9\4b\70\0c\cc\9e\1a\d3\2f\b7\52\2f\20\3b\eb\64\51\1d\a0\2d\b2\3e\be\13\85\48\92\32\2e\db\5c\a1\e7\8c\45\91\35\01\0a\93\c2\eb\09\ce\f3\d2\22\24\d0\8c\cc\1d\9d\38\c8\4d\e3\82\cc\64\15\06\2d\e7\01\2f\ab\bb\b5\04\4c\92\1c\7a\d6\3f\e8\5f\31\15\0c\dc\e4\31\b4\c4\25\3e\2a\aa\00\9e\c8\e5\21\7a\7f\29\f1\c0\af\1d\5e\e8\63\39\ad\f8\7e\6c\c8\c5\7f\c2\a8\97\27\0a\d9\f4\21\6a\ea\03\09\fb\f7\96\3b\83\79\5f\7c\4b\30\9f\56\35\de\b4\73\d4\95\f0\14\c3\74\2f\0d\a3\1d\4e\8d\31\24\b3\1a\84\85\62\5a\7b\3c\14\39\17\e6\6d\eb\37\c2\00\58\5b\0b\e3\3c\8a\62\e1\f8\35\4b\56\e2\87\60\8b\be\a7\38\91\77\54\a9\5a\24\25\90\9f\a5\42\77\f3\5c\39\df\ff\74\07\76\a1\cd\1f\62\0b\81\81\68\af\05\c1\c0\7f\26\ee\c0\91\a3\6a\7d\29\61\45\27\e5\57\88\dc\0d\97\04\1a\33\a9\44\8a\da\02\10\45\3f\8e\55\a6\76\8c\4d\e3\f1\89\83\c8\d0\f8\9b\50\77\9f\47\df\4c\9c\66\0d\aa\18\b8\5f\4f\c4\01\ce\dc\84\ac\46\9e\69\e1\76\45\6b\61\89\e4\5d\94\bb\11\83\9f\78\d8\0a\d2\f5\7e\5d\43\ea\bc\10\f1\3a\c9\e2\64\fb\53\65\d0\c7\b4\a7\fb\d4\05\53\25\d0\cd\29\88\00\56\25\24\7d\5d\b4\f3\41\9f\e9\b5\f7\ae\64\2c\e3\c9\6d\d5\84\3a\72\12\b8\7a\d9\1b\09\e8\38\da\26\4f\04\ce\03\71\6e\8a\44\7b\5c\81\59\9c\d2\e4\c3\ba\59\a6\e5\28\a7\8f\9a\e4\d5\4e\b9\ca\7f\cb\75\b8\2b\43\3e\b3\15\46\b1\a5\bc\9d\9e\38\15\f1\bd\1b\21\aa\f1\82\00\95\fc\a7\77\47\39\a7\33\43\92\d7\52\40\4b\06\81\8a\a0\bd\f1\6b\99\84\42\5b\e2\3b\c5\5e\12\5c\28\4d\b6\0e\4e\c8\5c\e8\01\8a\c5\e7\e4\9d\42\ee\5d\9c\c4\eb\eb\68\09\27\92\95\9a\11\54\73\c4\12\80\fb\7d\fe\c5\08\60\7f\36\41\e0\10\ba\d6\2b\6c\f1\b4\17\fe\26\34\e3\4b\f8\a8\e3\91\be\4f\2a\fc\da\81\b8\e7\fe\d5\26\50\47\f3\1a\65\32\81\e0\05\b8\4f\32\31\26\00\4a\53\97\c2\c3\0e\2e\a1\26\54\ab\05\8e\56\2f\7d\af\22\84\68\a5\8b\97\f6\a4\fd\a8\cc\75\41\96\86\fd\27\3d\29\86\8d\7f\4c\d4\8e\73\41\f4\1e\e2\dd\58\27\97\ce\9c\94\cf\7a\04\2f\dc\ed") + ) + + (func $f64.kahan_sum (param $p i32) (param $n i32) (result f64) + (local $sum f64) + (local $c f64) + (local $t f64) + (loop $exit $top + (set_local $t (f64.sub (f64.sub (set_local $sum (f64.add (get_local $c) (set_local $t (f64.sub (f64.load (get_local $p)) (get_local $t))))) (get_local $c)) (get_local $t))) + (set_local $p (i32.add (get_local $p) (i32.const 8))) + (set_local $c (get_local $sum)) + (br_if $top (set_local $n (i32.add (get_local $n) (i32.const -1)))) + ) + (get_local $sum) + ) + (export "f64.kahan_sum" $f64.kahan_sum) + + (func $f64.plain_sum (param $p i32) (param $n i32) (result f64) + (local $sum f64) + (loop $exit $top + (set_local $sum (f64.add (get_local $sum) (f64.load (get_local $p)))) + (set_local $p (i32.add (get_local $p) (i32.const 8))) + (set_local $n (i32.add (get_local $n) (i32.const -1))) + (br_if $top (get_local $n)) + ) + (get_local $sum) + ) + (export "f64.plain_sum" $f64.plain_sum) +) + +(assert_return (invoke "f64.kahan_sum" (i32.const 0) (i32.const 256)) (f64.const 0x1.dd7cb2a5ffc88p+998)) +(assert_return (invoke "f64.plain_sum" (i32.const 0) (i32.const 256)) (f64.const 0x1.dd7cb2a63fc87p+998)) From 14bbaa0f630c078280bd88c8b18dccfe6ce984fa Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 27 Apr 2016 07:14:05 -0700 Subject: [PATCH 10/31] Test that negates are not folded away at the expense of negative zero. --- ml-proto/test/float_exprs.wast | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/ml-proto/test/float_exprs.wast b/ml-proto/test/float_exprs.wast index 1705566f53..0eaf3b0cf2 100644 --- a/ml-proto/test/float_exprs.wast +++ b/ml-proto/test/float_exprs.wast @@ -1481,3 +1481,25 @@ (assert_return (invoke "f64.kahan_sum" (i32.const 0) (i32.const 256)) (f64.const 0x1.dd7cb2a5ffc88p+998)) (assert_return (invoke "f64.plain_sum" (i32.const 0) (i32.const 256)) (f64.const 0x1.dd7cb2a63fc87p+998)) + +;; Test that -(x - y) is not folded to y - x. + +(module + (func $f32.no_fold_neg_sub (param $x f32) (param $y f32) (result f32) + (f32.neg (f32.sub (get_local $x) (get_local $y)))) + (export "f32.no_fold_neg_sub" $f32.no_fold_neg_sub) + + (func $f64.no_fold_neg_sub (param $x f64) (param $y f64) (result f64) + (f64.neg (f64.sub (get_local $x) (get_local $y)))) + (export "f64.no_fold_neg_sub" $f64.no_fold_neg_sub) +) + +(assert_return (invoke "f32.no_fold_neg_sub" (f32.const -0.0) (f32.const -0.0)) (f32.const -0.0)) +(assert_return (invoke "f32.no_fold_neg_sub" (f32.const 0.0) (f32.const -0.0)) (f32.const -0.0)) +(assert_return (invoke "f32.no_fold_neg_sub" (f32.const -0.0) (f32.const 0.0)) (f32.const 0.0)) +(assert_return (invoke "f32.no_fold_neg_sub" (f32.const 0.0) (f32.const -0.0)) (f32.const -0.0)) + +(assert_return (invoke "f64.no_fold_neg_sub" (f64.const -0.0) (f64.const -0.0)) (f64.const -0.0)) +(assert_return (invoke "f64.no_fold_neg_sub" (f64.const 0.0) (f64.const -0.0)) (f64.const -0.0)) +(assert_return (invoke "f64.no_fold_neg_sub" (f64.const -0.0) (f64.const 0.0)) (f64.const 0.0)) +(assert_return (invoke "f64.no_fold_neg_sub" (f64.const 0.0) (f64.const -0.0)) (f64.const -0.0)) From cba6cad55b1e53d9f1cd4a90e29d9a9f7985f2e4 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 27 Apr 2016 07:14:07 -0700 Subject: [PATCH 11/31] Test that x + -x is not folded away. --- ml-proto/test/float_exprs.wast | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/ml-proto/test/float_exprs.wast b/ml-proto/test/float_exprs.wast index 0eaf3b0cf2..1e0c78ebb8 100644 --- a/ml-proto/test/float_exprs.wast +++ b/ml-proto/test/float_exprs.wast @@ -1503,3 +1503,25 @@ (assert_return (invoke "f64.no_fold_neg_sub" (f64.const 0.0) (f64.const -0.0)) (f64.const -0.0)) (assert_return (invoke "f64.no_fold_neg_sub" (f64.const -0.0) (f64.const 0.0)) (f64.const 0.0)) (assert_return (invoke "f64.no_fold_neg_sub" (f64.const 0.0) (f64.const -0.0)) (f64.const -0.0)) + +;; Test that -x + x is not folded to 0.0. + +(module + (func $f32.no_fold_add_neg (param $x f32) (result f32) + (f32.add (f32.neg (get_local $x)) (get_local $x))) + (export "f32.no_fold_add_neg" $f32.no_fold_add_neg) + + (func $f64.no_fold_add_neg (param $x f64) (result f64) + (f64.add (f64.neg (get_local $x)) (get_local $x))) + (export "f64.no_fold_add_neg" $f64.no_fold_add_neg) +) + +(assert_return (invoke "f32.no_fold_add_neg" (f32.const 0.0)) (f32.const 0.0)) +(assert_return (invoke "f32.no_fold_add_neg" (f32.const -0.0)) (f32.const 0.0)) +(assert_return_nan (invoke "f32.no_fold_add_neg" (f32.const infinity))) +(assert_return_nan (invoke "f32.no_fold_add_neg" (f32.const -infinity))) + +(assert_return (invoke "f64.no_fold_add_neg" (f64.const 0.0)) (f64.const 0.0)) +(assert_return (invoke "f64.no_fold_add_neg" (f64.const -0.0)) (f64.const 0.0)) +(assert_return_nan (invoke "f64.no_fold_add_neg" (f64.const infinity))) +(assert_return_nan (invoke "f64.no_fold_add_neg" (f64.const -infinity))) From 29c4e71f11043f05cd728fbd7dbbb48e1e3c62e9 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 27 Apr 2016 07:14:08 -0700 Subject: [PATCH 12/31] Test that addition is not folded to multiplication with different rounding. --- ml-proto/test/float_exprs.wast | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/ml-proto/test/float_exprs.wast b/ml-proto/test/float_exprs.wast index 1e0c78ebb8..8825a24db2 100644 --- a/ml-proto/test/float_exprs.wast +++ b/ml-proto/test/float_exprs.wast @@ -1525,3 +1525,33 @@ (assert_return (invoke "f64.no_fold_add_neg" (f64.const -0.0)) (f64.const 0.0)) (assert_return_nan (invoke "f64.no_fold_add_neg" (f64.const infinity))) (assert_return_nan (invoke "f64.no_fold_add_neg" (f64.const -infinity))) + +;; Test that x+x+x+x+x+x+x is not folded to x * 7. + +(module + (func $f32.no_fold_7x_via_add (param $x f32) (result f32) + (f32.add (f32.add (f32.add (f32.add (f32.add (f32.add + (get_local $x) + (get_local $x)) (get_local $x)) (get_local $x)) + (get_local $x)) (get_local $x)) (get_local $x))) + (export "f32.no_fold_7x_via_add" $f32.no_fold_7x_via_add) + + (func $f64.no_fold_7x_via_add (param $x f64) (result f64) + (f64.add (f64.add (f64.add (f64.add (f64.add (f64.add + (get_local $x) + (get_local $x)) (get_local $x)) (get_local $x)) + (get_local $x)) (get_local $x)) (get_local $x))) + (export "f64.no_fold_7x_via_add" $f64.no_fold_7x_via_add) +) + +(assert_return (invoke "f32.no_fold_7x_via_add" (f32.const -0x1.30f15cp+21)) (f32.const -0x1.0ad332p+24)) +(assert_return (invoke "f32.no_fold_7x_via_add" (f32.const 0x1.a51c14p+11)) (f32.const 0x1.70789p+14)) +(assert_return (invoke "f32.no_fold_7x_via_add" (f32.const 0x1.f03e64p-116)) (f32.const 0x1.b23696p-113)) +(assert_return (invoke "f32.no_fold_7x_via_add" (f32.const -0x1.f15fecp-85)) (f32.const -0x1.b333fp-82)) +(assert_return (invoke "f32.no_fold_7x_via_add" (f32.const -0x1.1a38aep-71)) (f32.const -0x1.ede332p-69)) + +(assert_return (invoke "f64.no_fold_7x_via_add" (f64.const -0x1.07899efbf7601p+404)) (f64.const -0x1.cd30d638f0e81p+406)) +(assert_return (invoke "f64.no_fold_7x_via_add" (f64.const -0x1.0f4ae73f5f74bp-412)) (f64.const -0x1.dac314aee70c4p-410)) +(assert_return (invoke "f64.no_fold_7x_via_add" (f64.const -0x1.1eb6bb5682abap+554)) (f64.const -0x1.f5bfc7d764ac4p+556)) +(assert_return (invoke "f64.no_fold_7x_via_add" (f64.const 0x1.5c23a99615d72p+65)) (f64.const 0x1.309f3463531c3p+68)) +(assert_return (invoke "f64.no_fold_7x_via_add" (f64.const 0x1.cc7846ee11dd4p+397)) (f64.const 0x1.92e93e104fa18p+400)) From 5df771ecc5bdb0eb81120ca61bf032bdda740f17 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 27 Apr 2016 07:14:10 -0700 Subject: [PATCH 13/31] Test the reinterpret conversions with more special values. --- ml-proto/test/conversions.wast | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/ml-proto/test/conversions.wast b/ml-proto/test/conversions.wast index 0fe93e6120..b5c5e0eedf 100644 --- a/ml-proto/test/conversions.wast +++ b/ml-proto/test/conversions.wast @@ -395,12 +395,24 @@ (assert_return (invoke "f32.reinterpret_i32" (i32.const 1)) (f32.const 0x1p-149)) (assert_return (invoke "f32.reinterpret_i32" (i32.const 123456789)) (f32.const 0x1.b79a2ap-113)) (assert_return (invoke "f32.reinterpret_i32" (i32.const -2147483647)) (f32.const -0x1p-149)) +(assert_return (invoke "f32.reinterpret_i32" (i32.const 0x7f800000)) (f32.const infinity)) +(assert_return (invoke "f32.reinterpret_i32" (i32.const 0xff800000)) (f32.const -infinity)) +(assert_return (invoke "f32.reinterpret_i32" (i32.const 0x7fc00000)) (f32.const nan)) +(assert_return (invoke "f32.reinterpret_i32" (i32.const 0xffc00000)) (f32.const -nan)) +(assert_return (invoke "f32.reinterpret_i32" (i32.const 0x7fa00000)) (f32.const nan:0x200000)) +(assert_return (invoke "f32.reinterpret_i32" (i32.const 0xffa00000)) (f32.const -nan:0x200000)) (assert_return (invoke "f64.reinterpret_i64" (i64.const 0)) (f64.const 0.0)) (assert_return (invoke "f64.reinterpret_i64" (i64.const 1)) (f64.const 0x0.0000000000001p-1022)) (assert_return (invoke "f64.reinterpret_i64" (i64.const 0x8000000000000000)) (f64.const -0.0)) (assert_return (invoke "f64.reinterpret_i64" (i64.const 1234567890)) (f64.const 0x0.00000499602d2p-1022)) (assert_return (invoke "f64.reinterpret_i64" (i64.const -9223372036854775807)) (f64.const -0x0.0000000000001p-1022)) +(assert_return (invoke "f64.reinterpret_i64" (i64.const 0x7ff0000000000000)) (f64.const infinity)) +(assert_return (invoke "f64.reinterpret_i64" (i64.const 0xfff0000000000000)) (f64.const -infinity)) +(assert_return (invoke "f64.reinterpret_i64" (i64.const 0x7ff8000000000000)) (f64.const nan)) +(assert_return (invoke "f64.reinterpret_i64" (i64.const 0xfff8000000000000)) (f64.const -nan)) +(assert_return (invoke "f64.reinterpret_i64" (i64.const 0x7ff4000000000000)) (f64.const nan:0x4000000000000)) +(assert_return (invoke "f64.reinterpret_i64" (i64.const 0xfff4000000000000)) (f64.const -nan:0x4000000000000)) (assert_return (invoke "i32.reinterpret_f32" (f32.const 0.0)) (i32.const 0)) (assert_return (invoke "i32.reinterpret_f32" (f32.const -0.0)) (i32.const 0x80000000)) @@ -413,6 +425,9 @@ (assert_return (invoke "i32.reinterpret_f32" (f32.const infinity)) (i32.const 0x7f800000)) (assert_return (invoke "i32.reinterpret_f32" (f32.const -infinity)) (i32.const 0xff800000)) (assert_return (invoke "i32.reinterpret_f32" (f32.const nan)) (i32.const 0x7fc00000)) +(assert_return (invoke "i32.reinterpret_f32" (f32.const -nan)) (i32.const 0xffc00000)) +(assert_return (invoke "i32.reinterpret_f32" (f32.const nan:0x200000)) (i32.const 0x7fa00000)) +(assert_return (invoke "i32.reinterpret_f32" (f32.const -nan:0x200000)) (i32.const 0xffa00000)) (assert_return (invoke "i64.reinterpret_f64" (f64.const 0.0)) (i64.const 0)) (assert_return (invoke "i64.reinterpret_f64" (f64.const -0.0)) (i64.const 0x8000000000000000)) @@ -425,3 +440,6 @@ (assert_return (invoke "i64.reinterpret_f64" (f64.const infinity)) (i64.const 0x7ff0000000000000)) (assert_return (invoke "i64.reinterpret_f64" (f64.const -infinity)) (i64.const 0xfff0000000000000)) (assert_return (invoke "i64.reinterpret_f64" (f64.const nan)) (i64.const 0x7ff8000000000000)) +(assert_return (invoke "i64.reinterpret_f64" (f64.const -nan)) (i64.const 0xfff8000000000000)) +(assert_return (invoke "i64.reinterpret_f64" (f64.const nan:0x4000000000000)) (i64.const 0x7ff4000000000000)) +(assert_return (invoke "i64.reinterpret_f64" (f64.const -nan:0x4000000000000)) (i64.const 0xfff4000000000000)) From 76bd56e39cd01ac063d38d8706ff02fcb7f0f857 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 27 Apr 2016 07:14:12 -0700 Subject: [PATCH 14/31] Test demote(promote(x)). --- ml-proto/test/float_exprs.wast | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ml-proto/test/float_exprs.wast b/ml-proto/test/float_exprs.wast index 8825a24db2..841cc51312 100644 --- a/ml-proto/test/float_exprs.wast +++ b/ml-proto/test/float_exprs.wast @@ -685,6 +685,16 @@ (assert_return (invoke "no_fold_demote_promote" (f64.const -0x1.74f5bd865163p-88)) (f64.const -0x1.74f5bep-88)) (assert_return (invoke "no_fold_demote_promote" (f64.const 0x1.26d675662367ep+104)) (f64.const 0x1.26d676p+104)) +;; Test that demote(promote(x)) is not folded to x. + +(module + (func $no_fold_promote_demote (param $x f32) (result f32) + (f32.demote/f64 (f64.promote/f32 (get_local $x)))) + (export "no_fold_promote_demote" $no_fold_promote_demote) +) + +(assert_return (invoke "no_fold_promote_demote" (f32.const nan:0x200000)) (f32.const nan:0x600000)) + ;; Test that demote(x+promote(y)) is not folded to demote(x)+y. (module From 022ae0c9ef42341b9fe9d2c9ff92a2fa6af85c07 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 27 Apr 2016 07:14:13 -0700 Subject: [PATCH 15/31] Test reinterpret cast with -1. --- ml-proto/test/conversions.wast | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ml-proto/test/conversions.wast b/ml-proto/test/conversions.wast index b5c5e0eedf..938ccf372b 100644 --- a/ml-proto/test/conversions.wast +++ b/ml-proto/test/conversions.wast @@ -393,6 +393,7 @@ (assert_return (invoke "f32.reinterpret_i32" (i32.const 0)) (f32.const 0.0)) (assert_return (invoke "f32.reinterpret_i32" (i32.const 0x80000000)) (f32.const -0.0)) (assert_return (invoke "f32.reinterpret_i32" (i32.const 1)) (f32.const 0x1p-149)) +(assert_return (invoke "f32.reinterpret_i32" (i32.const -1)) (f32.const -nan:0x7fffff)) (assert_return (invoke "f32.reinterpret_i32" (i32.const 123456789)) (f32.const 0x1.b79a2ap-113)) (assert_return (invoke "f32.reinterpret_i32" (i32.const -2147483647)) (f32.const -0x1p-149)) (assert_return (invoke "f32.reinterpret_i32" (i32.const 0x7f800000)) (f32.const infinity)) @@ -404,6 +405,7 @@ (assert_return (invoke "f64.reinterpret_i64" (i64.const 0)) (f64.const 0.0)) (assert_return (invoke "f64.reinterpret_i64" (i64.const 1)) (f64.const 0x0.0000000000001p-1022)) +(assert_return (invoke "f64.reinterpret_i64" (i64.const -1)) (f64.const -nan:0xfffffffffffff)) (assert_return (invoke "f64.reinterpret_i64" (i64.const 0x8000000000000000)) (f64.const -0.0)) (assert_return (invoke "f64.reinterpret_i64" (i64.const 1234567890)) (f64.const 0x0.00000499602d2p-1022)) (assert_return (invoke "f64.reinterpret_i64" (i64.const -9223372036854775807)) (f64.const -0x0.0000000000001p-1022)) @@ -417,6 +419,7 @@ (assert_return (invoke "i32.reinterpret_f32" (f32.const 0.0)) (i32.const 0)) (assert_return (invoke "i32.reinterpret_f32" (f32.const -0.0)) (i32.const 0x80000000)) (assert_return (invoke "i32.reinterpret_f32" (f32.const 0x1p-149)) (i32.const 1)) +(assert_return (invoke "i32.reinterpret_f32" (f32.const -nan:0x7fffff)) (i32.const -1)) (assert_return (invoke "i32.reinterpret_f32" (f32.const -0x1p-149)) (i32.const 0x80000001)) (assert_return (invoke "i32.reinterpret_f32" (f32.const 1.0)) (i32.const 1065353216)) (assert_return (invoke "i32.reinterpret_f32" (f32.const 3.1415926)) (i32.const 1078530010)) @@ -432,6 +435,7 @@ (assert_return (invoke "i64.reinterpret_f64" (f64.const 0.0)) (i64.const 0)) (assert_return (invoke "i64.reinterpret_f64" (f64.const -0.0)) (i64.const 0x8000000000000000)) (assert_return (invoke "i64.reinterpret_f64" (f64.const 0x0.0000000000001p-1022)) (i64.const 1)) +(assert_return (invoke "i64.reinterpret_f64" (f64.const -nan:0xfffffffffffff)) (i64.const -1)) (assert_return (invoke "i64.reinterpret_f64" (f64.const -0x0.0000000000001p-1022)) (i64.const 0x8000000000000001)) (assert_return (invoke "i64.reinterpret_f64" (f64.const 1.0)) (i64.const 4607182418800017408)) (assert_return (invoke "i64.reinterpret_f64" (f64.const 3.14159265358979)) (i64.const 4614256656552045841)) From d215bb9324d2a3133ac97f9e6ee741f314cba0ef Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 27 Apr 2016 07:14:14 -0700 Subject: [PATCH 16/31] Test an interesting division boundary case. --- ml-proto/test/float_misc.wast | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ml-proto/test/float_misc.wast b/ml-proto/test/float_misc.wast index e161c0c27a..f50324be3e 100644 --- a/ml-proto/test/float_misc.wast +++ b/ml-proto/test/float_misc.wast @@ -403,6 +403,12 @@ (assert_return (invoke "f64.div" (f64.const 0x1.cf82510d0ae6bp+89) (f64.const 0x1.0207d86498053p+97)) (f64.const 0x1.cbdc804e2cf14p-8)) (assert_return (invoke "f64.div" (f64.const 0x1.4c82cbb508e21p-11) (f64.const -0x1.6b57208c2d5d5p+52)) (f64.const -0x1.d48e8b369129ap-64)) +;; Division involving the maximum subnormal value and the minimum normal value. +(assert_return (invoke "f32.div" (f32.const 0x1p-126) (f32.const 0x1.fffffcp-127)) (f32.const 0x1.000002p+0)) +(assert_return (invoke "f32.div" (f32.const 0x1.fffffcp-127) (f32.const 0x1p-126)) (f32.const 0x1.fffffcp-1)) +(assert_return (invoke "f64.div" (f64.const 0x1p-1022) (f64.const 0x0.fffffffffffffp-1022)) (f64.const 0x1.0000000000001p+0)) +(assert_return (invoke "f64.div" (f64.const 0x0.fffffffffffffp-1022) (f64.const 0x1p-1022)) (f64.const 0x1.ffffffffffffep-1)) + ;; Test for bugs found in an early RISC-V implementation. ;; https://github.com/riscv/riscv-tests/pull/8 (assert_return (invoke "f32.sqrt" (f32.const 0x1.56p+7)) (f32.const 0x1.a2744cp+3)) From 0e7bb39dbff0e2aa4d380b446fa97d0e429e54a8 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 27 Apr 2016 07:14:16 -0700 Subject: [PATCH 17/31] Test the minimum valid value for trunc_u conversions. --- ml-proto/test/conversions.wast | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ml-proto/test/conversions.wast b/ml-proto/test/conversions.wast index 938ccf372b..4671b0d4ae 100644 --- a/ml-proto/test/conversions.wast +++ b/ml-proto/test/conversions.wast @@ -134,6 +134,7 @@ (assert_return (invoke "i32.trunc_u_f32" (f32.const 2147483648)) (i32.const -2147483648)) ;; 0x1.00000p+31 -> 8000 0000 (assert_return (invoke "i32.trunc_u_f32" (f32.const 4294967040.0)) (i32.const -256)) (assert_return (invoke "i32.trunc_u_f32" (f32.const -0x1.ccccccp-1)) (i32.const 0)) +(assert_return (invoke "i32.trunc_u_f32" (f32.const -0x1.fffffep-1)) (i32.const 0)) (assert_trap (invoke "i32.trunc_u_f32" (f32.const 4294967296.0)) "integer overflow") (assert_trap (invoke "i32.trunc_u_f32" (f32.const -1.0)) "integer overflow") (assert_trap (invoke "i32.trunc_u_f32" (f32.const infinity)) "integer overflow") @@ -172,6 +173,7 @@ (assert_return (invoke "i32.trunc_u_f64" (f64.const 2147483648)) (i32.const -2147483648)) ;; 0x1.00000p+31 -> 8000 0000 (assert_return (invoke "i32.trunc_u_f64" (f64.const 4294967295.0)) (i32.const -1)) (assert_return (invoke "i32.trunc_u_f64" (f64.const -0x1.ccccccccccccdp-1)) (i32.const 0)) +(assert_return (invoke "i32.trunc_u_f64" (f64.const -0x1.fffffffffffffp-1)) (i32.const 0)) (assert_return (invoke "i32.trunc_u_f64" (f64.const 1e8)) (i32.const 100000000)) (assert_trap (invoke "i32.trunc_u_f64" (f64.const 4294967296.0)) "integer overflow") (assert_trap (invoke "i32.trunc_u_f64" (f64.const -1.0)) "integer overflow") @@ -214,6 +216,7 @@ (assert_return (invoke "i64.trunc_u_f32" (f32.const 4294967296)) (i64.const 4294967296)) (assert_return (invoke "i64.trunc_u_f32" (f32.const 18446742974197923840.0)) (i64.const -1099511627776)) (assert_return (invoke "i64.trunc_u_f32" (f32.const -0x1.ccccccp-1)) (i64.const 0)) +(assert_return (invoke "i64.trunc_u_f32" (f32.const -0x1.fffffep-1)) (i64.const 0)) (assert_trap (invoke "i64.trunc_u_f32" (f32.const 18446744073709551616.0)) "integer overflow") (assert_trap (invoke "i64.trunc_u_f32" (f32.const -1.0)) "integer overflow") (assert_trap (invoke "i64.trunc_u_f32" (f32.const infinity)) "integer overflow") @@ -253,6 +256,7 @@ (assert_return (invoke "i64.trunc_u_f64" (f64.const 4294967296)) (i64.const 0x100000000)) (assert_return (invoke "i64.trunc_u_f64" (f64.const 18446744073709549568.0)) (i64.const -2048)) (assert_return (invoke "i64.trunc_u_f64" (f64.const -0x1.ccccccccccccdp-1)) (i64.const 0)) +(assert_return (invoke "i64.trunc_u_f64" (f64.const -0x1.fffffffffffffp-1)) (i64.const 0)) (assert_return (invoke "i64.trunc_u_f64" (f64.const 1e8)) (i64.const 100000000)) (assert_return (invoke "i64.trunc_u_f64" (f64.const 1e16)) (i64.const 10000000000000000)) (assert_return (invoke "i64.trunc_u_f64" (f64.const 9223372036854775808)) (i64.const -9223372036854775808)) From f68690f9e61f3b47dbbd5d6b9a1778a6c83ab9d6 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 27 Apr 2016 07:14:17 -0700 Subject: [PATCH 18/31] Test min and max with signaling NaNs. --- ml-proto/test/float_misc.wast | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/ml-proto/test/float_misc.wast b/ml-proto/test/float_misc.wast index f50324be3e..5e7ee069f5 100644 --- a/ml-proto/test/float_misc.wast +++ b/ml-proto/test/float_misc.wast @@ -26,6 +26,8 @@ (func $f32.floor (param $x f32) (result f32) (f32.floor (get_local $x))) (func $f32.trunc (param $x f32) (result f32) (f32.trunc (get_local $x))) (func $f32.nearest (param $x f32) (result f32) (f32.nearest (get_local $x))) + (func $f32.min (param $x f32) (param $y f32) (result f32) (f32.min (get_local $x) (get_local $y))) + (func $f32.max (param $x f32) (param $y f32) (result f32) (f32.max (get_local $x) (get_local $y))) (func $f64.add (param $x f64) (param $y f64) (result f64) (f64.add (get_local $x) (get_local $y))) (func $f64.sub (param $x f64) (param $y f64) (result f64) (f64.sub (get_local $x) (get_local $y))) @@ -39,6 +41,8 @@ (func $f64.floor (param $x f64) (result f64) (f64.floor (get_local $x))) (func $f64.trunc (param $x f64) (result f64) (f64.trunc (get_local $x))) (func $f64.nearest (param $x f64) (result f64) (f64.nearest (get_local $x))) + (func $f64.min (param $x f64) (param $y f64) (result f64) (f64.min (get_local $x) (get_local $y))) + (func $f64.max (param $x f64) (param $y f64) (result f64) (f64.max (get_local $x) (get_local $y))) (export "f32.add" $f32.add) (export "f32.sub" $f32.sub) @@ -52,6 +56,8 @@ (export "f32.floor" $f32.floor) (export "f32.trunc" $f32.trunc) (export "f32.nearest" $f32.nearest) + (export "f32.min" $f32.min) + (export "f32.max" $f32.max) (export "f64.add" $f64.add) (export "f64.sub" $f64.sub) @@ -65,6 +71,8 @@ (export "f64.floor" $f64.floor) (export "f64.trunc" $f64.trunc) (export "f64.nearest" $f64.nearest) + (export "f64.min" $f64.min) + (export "f64.max" $f64.max) ) (assert_return (invoke "f32.add" (f32.const 1.1234567890) (f32.const 1.2345e-10)) (f32.const 1.123456789)) @@ -547,3 +555,13 @@ (assert_return (invoke "f64.nearest" (f64.const 4.5)) (f64.const 4.0)) (assert_return (invoke "f64.nearest" (f64.const -4.5)) (f64.const -4.0)) (assert_return (invoke "f64.nearest" (f64.const -3.5)) (f64.const -4.0)) + +;; Test that min and max behave properly with signaling NaNs. +(assert_return (invoke "f32.min" (f32.const 0.0) (f32.const nan:0x200000)) (f32.const nan:0x600000)) +(assert_return (invoke "f32.min" (f32.const nan:0x200000) (f32.const 0.0)) (f32.const nan:0x600000)) +(assert_return (invoke "f32.max" (f32.const 0.0) (f32.const nan:0x200000)) (f32.const nan:0x600000)) +(assert_return (invoke "f32.max" (f32.const nan:0x200000) (f32.const 0.0)) (f32.const nan:0x600000)) +(assert_return (invoke "f64.min" (f64.const 0.0) (f64.const nan:0x4000000000000)) (f64.const nan:0xc000000000000)) +(assert_return (invoke "f64.min" (f64.const nan:0x4000000000000) (f64.const 0.0)) (f64.const nan:0xc000000000000)) +(assert_return (invoke "f64.max" (f64.const 0.0) (f64.const nan:0x4000000000000)) (f64.const nan:0xc000000000000)) +(assert_return (invoke "f64.max" (f64.const nan:0x4000000000000) (f64.const 0.0)) (f64.const nan:0xc000000000000)) From 90251d5c11981c6b5176398491442775a173e049 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 27 Apr 2016 07:14:19 -0700 Subject: [PATCH 19/31] Test the least value with a positive quotient with the maximum value. --- ml-proto/test/float_misc.wast | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ml-proto/test/float_misc.wast b/ml-proto/test/float_misc.wast index 5e7ee069f5..43e32b45f0 100644 --- a/ml-proto/test/float_misc.wast +++ b/ml-proto/test/float_misc.wast @@ -417,6 +417,12 @@ (assert_return (invoke "f64.div" (f64.const 0x1p-1022) (f64.const 0x0.fffffffffffffp-1022)) (f64.const 0x1.0000000000001p+0)) (assert_return (invoke "f64.div" (f64.const 0x0.fffffffffffffp-1022) (f64.const 0x1p-1022)) (f64.const 0x1.ffffffffffffep-1)) +;; Test the least value with a positive quotient with the maximum value. +(assert_return (invoke "f32.div" (f32.const 0x1.fffffep-23) (f32.const 0x1.fffffep+127)) (f32.const 0x0p+0)) +(assert_return (invoke "f32.div" (f32.const 0x1p-22) (f32.const 0x1.fffffep+127)) (f32.const 0x1p-149)) +(assert_return (invoke "f64.div" (f64.const 0x1.fffffffffffffp-52) (f64.const 0x1.fffffffffffffp+1023)) (f64.const 0x0p+0)) +(assert_return (invoke "f64.div" (f64.const 0x1p-51) (f64.const 0x1.fffffffffffffp+1023)) (f64.const 0x0.0000000000001p-1022)) + ;; Test for bugs found in an early RISC-V implementation. ;; https://github.com/riscv/riscv-tests/pull/8 (assert_return (invoke "f32.sqrt" (f32.const 0x1.56p+7)) (f32.const 0x1.a2744cp+3)) From 5b9f383293ed6e79f57fdff02d0a980de5e93255 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 27 Apr 2016 07:14:20 -0700 Subject: [PATCH 20/31] Test the least value with a positive square. --- ml-proto/test/float_misc.wast | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ml-proto/test/float_misc.wast b/ml-proto/test/float_misc.wast index 43e32b45f0..cdbbc2fe82 100644 --- a/ml-proto/test/float_misc.wast +++ b/ml-proto/test/float_misc.wast @@ -327,6 +327,12 @@ (assert_return (invoke "f64.mul" (f64.const 0x1.e4d235961d543p-373) (f64.const 0x1.bc56f20ef9a48p-205)) (f64.const 0x1.a4c09efcb71d6p-577)) (assert_return (invoke "f64.mul" (f64.const -0x1.b9612e66faba8p+77) (f64.const 0x1.e2bc6aa782273p-348)) (f64.const -0x1.a026ea4f81db1p-270)) +;; Test the least value with a positive square. +(assert_return (invoke "f32.mul" (f32.const 0x1p-75) (f32.const 0x1p-75)) (f32.const 0x0p+0)) +(assert_return (invoke "f32.mul" (f32.const 0x1.000002p-75) (f32.const 0x1.000002p-75)) (f32.const 0x1p-149)) +(assert_return (invoke "f64.mul" (f64.const 0x1.6a09e667f3bccp-538) (f64.const 0x1.6a09e667f3bccp-538)) (f64.const 0x0p+0)) +(assert_return (invoke "f64.mul" (f64.const 0x1.6a09e667f3bcdp-538) (f64.const 0x1.6a09e667f3bcdp-538)) (f64.const 0x0.0000000000001p-1022)) + (assert_return (invoke "f32.div" (f32.const 1.123456789) (f32.const 100)) (f32.const 0x1.702264p-7)) (assert_return (invoke "f32.div" (f32.const 8391667.0) (f32.const 12582905.0)) (f32.const 0x1.55754p-1)) (assert_return (invoke "f32.div" (f32.const 65536.0) (f32.const 0x1p-37)) (f32.const 0x1p+53)) From 3af8a8e1a33eb4e475c7cb14385fc7c5ffebe605 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 27 Apr 2016 07:14:22 -0700 Subject: [PATCH 21/31] Test the least value with a finite reciprocal. --- ml-proto/test/float_misc.wast | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ml-proto/test/float_misc.wast b/ml-proto/test/float_misc.wast index cdbbc2fe82..3ea32a0c7b 100644 --- a/ml-proto/test/float_misc.wast +++ b/ml-proto/test/float_misc.wast @@ -429,6 +429,12 @@ (assert_return (invoke "f64.div" (f64.const 0x1.fffffffffffffp-52) (f64.const 0x1.fffffffffffffp+1023)) (f64.const 0x0p+0)) (assert_return (invoke "f64.div" (f64.const 0x1p-51) (f64.const 0x1.fffffffffffffp+1023)) (f64.const 0x0.0000000000001p-1022)) +;; Test the least value with a finite reciprocal. +(assert_return (invoke "f32.div" (f32.const 1.0) (f32.const 0x1p-128)) (f32.const infinity)) +(assert_return (invoke "f32.div" (f32.const 1.0) (f32.const 0x1.000008p-128)) (f32.const 0x1.fffffp+127)) +(assert_return (invoke "f64.div" (f64.const 1.0) (f64.const 0x0.4p-1022)) (f64.const infinity)) +(assert_return (invoke "f64.div" (f64.const 1.0) (f64.const 0x0.4000000000001p-1022)) (f64.const 0x1.ffffffffffff8p+1023)) + ;; Test for bugs found in an early RISC-V implementation. ;; https://github.com/riscv/riscv-tests/pull/8 (assert_return (invoke "f32.sqrt" (f32.const 0x1.56p+7)) (f32.const 0x1.a2744cp+3)) From 62cd0de990cc12e8ae82084d1ed6bb66594c8ce4 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 27 Apr 2016 07:14:23 -0700 Subject: [PATCH 22/31] Test that unaligned memory accesses don't canonicalize NaNs. --- ml-proto/test/float_memory.wast | 70 +++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/ml-proto/test/float_memory.wast b/ml-proto/test/float_memory.wast index efcb732c6e..b4ea4dcb8e 100644 --- a/ml-proto/test/float_memory.wast +++ b/ml-proto/test/float_memory.wast @@ -70,6 +70,76 @@ (assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000)) (assert_return (invoke "f64.load") (f64.const nan:0x4000000000000)) +;; Test that unaligned load and store do not canonicalize NaNs. + +(module + (memory 1 1 (segment 1 "\00\00\a0\7f")) + + (func $f32.load (result f32) (f32.load (i32.const 1))) + (export "f32.load" $f32.load) + + (func $i32.load (result i32) (i32.load (i32.const 1))) + (export "i32.load" $i32.load) + + (func $f32.store (f32.store (i32.const 1) (f32.const nan:0x200000))) + (export "f32.store" $f32.store) + + (func $i32.store (i32.store (i32.const 1) (i32.const 0x7fa00000))) + (export "i32.store" $i32.store) + + (func $reset (i32.store (i32.const 1) (i32.const 0))) + (export "reset" $reset) +) + +(assert_return (invoke "i32.load") (i32.const 0x7fa00000)) +(assert_return (invoke "f32.load") (f32.const nan:0x200000)) +(invoke "reset") +(assert_return (invoke "i32.load") (i32.const 0x0)) +(assert_return (invoke "f32.load") (f32.const 0.0)) +(invoke "f32.store") +(assert_return (invoke "i32.load") (i32.const 0x7fa00000)) +(assert_return (invoke "f32.load") (f32.const nan:0x200000)) +(invoke "reset") +(assert_return (invoke "i32.load") (i32.const 0x0)) +(assert_return (invoke "f32.load") (f32.const 0.0)) +(invoke "i32.store") +(assert_return (invoke "i32.load") (i32.const 0x7fa00000)) +(assert_return (invoke "f32.load") (f32.const nan:0x200000)) + +(module + (memory 1 1 (segment 1 "\00\00\00\00\00\00\f4\7f")) + + (func $f64.load (result f64) (f64.load (i32.const 1))) + (export "f64.load" $f64.load) + + (func $i64.load (result i64) (i64.load (i32.const 1))) + (export "i64.load" $i64.load) + + (func $f64.store (f64.store (i32.const 1) (f64.const nan:0x4000000000000))) + (export "f64.store" $f64.store) + + (func $i64.store (i64.store (i32.const 1) (i64.const 0x7ff4000000000000))) + (export "i64.store" $i64.store) + + (func $reset (i64.store (i32.const 1) (i64.const 0))) + (export "reset" $reset) +) + +(assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000)) +(assert_return (invoke "f64.load") (f64.const nan:0x4000000000000)) +(invoke "reset") +(assert_return (invoke "i64.load") (i64.const 0x0)) +(assert_return (invoke "f64.load") (f64.const 0.0)) +(invoke "f64.store") +(assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000)) +(assert_return (invoke "f64.load") (f64.const nan:0x4000000000000)) +(invoke "reset") +(assert_return (invoke "i64.load") (i64.const 0x0)) +(assert_return (invoke "f64.load") (f64.const 0.0)) +(invoke "i64.store") +(assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000)) +(assert_return (invoke "f64.load") (f64.const nan:0x4000000000000)) + ;; Test that load and store do not canonicalize NaNs as some JS engines do. (module From ddfdbd1db534125711c489aacb837ca01ea438c5 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 27 Apr 2016 07:14:24 -0700 Subject: [PATCH 23/31] Test that (x/y)/z is not optimized to x/(y*z). --- ml-proto/test/float_exprs.wast | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/ml-proto/test/float_exprs.wast b/ml-proto/test/float_exprs.wast index 841cc51312..f392d90eea 100644 --- a/ml-proto/test/float_exprs.wast +++ b/ml-proto/test/float_exprs.wast @@ -1565,3 +1565,28 @@ (assert_return (invoke "f64.no_fold_7x_via_add" (f64.const -0x1.1eb6bb5682abap+554)) (f64.const -0x1.f5bfc7d764ac4p+556)) (assert_return (invoke "f64.no_fold_7x_via_add" (f64.const 0x1.5c23a99615d72p+65)) (f64.const 0x1.309f3463531c3p+68)) (assert_return (invoke "f64.no_fold_7x_via_add" (f64.const 0x1.cc7846ee11dd4p+397)) (f64.const 0x1.92e93e104fa18p+400)) + +;; Test that (x/y)/z is not optimized to x/(y*z), +;; which is an "allowable alternative Form" in Fortran. + +(module + (func $f32.no_fold_div_div (param $x f32) (param $y f32) (param $z f32) (result f32) + (f32.div (f32.div (get_local $x) (get_local $y)) (get_local $z))) + (export "f32.no_fold_div_div" $f32.no_fold_div_div) + + (func $f64.no_fold_div_div (param $x f64) (param $y f64) (param $z f64) (result f64) + (f64.div (f64.div (get_local $x) (get_local $y)) (get_local $z))) + (export "f64.no_fold_div_div" $f64.no_fold_div_div) +) + +(assert_return (invoke "f32.no_fold_div_div" (f32.const -0x1.f70228p+78) (f32.const -0x1.fbc612p-16) (f32.const -0x1.8c379p+10)) (f32.const -0x1.47b43cp+83)) +(assert_return (invoke "f32.no_fold_div_div" (f32.const 0x1.d29d2ep-70) (f32.const 0x1.f3a17ep+110) (f32.const -0x1.64d41p-112)) (f32.const -0x0p+0)) +(assert_return (invoke "f32.no_fold_div_div" (f32.const 0x1.867f98p+43) (f32.const 0x1.30acfcp-105) (f32.const 0x1.e210d8p+105)) (f32.const infinity)) +(assert_return (invoke "f32.no_fold_div_div" (f32.const -0x1.c4001ap-14) (f32.const -0x1.9beb6cp+124) (f32.const -0x1.74f34cp-43)) (f32.const -0x1.819874p-96)) +(assert_return (invoke "f32.no_fold_div_div" (f32.const 0x1.db0e6ep+46) (f32.const 0x1.55eea2p+56) (f32.const -0x1.f3134p+124)) (f32.const -0x1.6cep-135)) + +(assert_return (invoke "f64.no_fold_div_div" (f64.const 0x1.b4dc8ec3c7777p+337) (f64.const 0x1.9f95ac2d1863p+584) (f64.const -0x1.d4318abba341ep-782)) (f64.const -0x1.2649159d87e02p+534)) +(assert_return (invoke "f64.no_fold_div_div" (f64.const -0x1.ac53af5eb445fp+791) (f64.const 0x1.8549c0a4ceb13p-29) (f64.const 0x1.64e384003c801p+316)) (f64.const -0x1.9417cdccbae91p+503)) +(assert_return (invoke "f64.no_fold_div_div" (f64.const -0x1.d2685afb27327p+2) (f64.const -0x1.abb1eeed3dbebp+880) (f64.const 0x1.a543e2e6968a3p+170)) (f64.const 0x0.0000002a69a5fp-1022)) +(assert_return (invoke "f64.no_fold_div_div" (f64.const -0x1.47ddede78ad1cp+825) (f64.const 0x1.6d932d070a367p-821) (f64.const 0x1.79cf18cc64fp+961)) (f64.const -infinity)) +(assert_return (invoke "f64.no_fold_div_div" (f64.const -0x1.f73d4979a9379p-888) (f64.const 0x1.4d83b53e97788p-596) (f64.const -0x1.f8f86c9603b5bp-139)) (f64.const 0x1.87a7bd89c586cp-154)) From c0edfbc405f5251613cb7be3b4238168b7fd6042 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 27 Apr 2016 07:14:26 -0700 Subject: [PATCH 24/31] Test that (x/y)*(z/w) is not optimized to (x*z)/(y*w). --- ml-proto/test/float_exprs.wast | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/ml-proto/test/float_exprs.wast b/ml-proto/test/float_exprs.wast index f392d90eea..fff762797c 100644 --- a/ml-proto/test/float_exprs.wast +++ b/ml-proto/test/float_exprs.wast @@ -1590,3 +1590,29 @@ (assert_return (invoke "f64.no_fold_div_div" (f64.const -0x1.d2685afb27327p+2) (f64.const -0x1.abb1eeed3dbebp+880) (f64.const 0x1.a543e2e6968a3p+170)) (f64.const 0x0.0000002a69a5fp-1022)) (assert_return (invoke "f64.no_fold_div_div" (f64.const -0x1.47ddede78ad1cp+825) (f64.const 0x1.6d932d070a367p-821) (f64.const 0x1.79cf18cc64fp+961)) (f64.const -infinity)) (assert_return (invoke "f64.no_fold_div_div" (f64.const -0x1.f73d4979a9379p-888) (f64.const 0x1.4d83b53e97788p-596) (f64.const -0x1.f8f86c9603b5bp-139)) (f64.const 0x1.87a7bd89c586cp-154)) + +;; Test that (x/y)*(z/w) is not optimized to (x*z)/(y*w), example from +;; http://perso.ens-lyon.fr/jean-michel.muller/Handbook.html +;; section 7.4.1: FORTRAN Floating Point in a Nutshell: Philosophy + +(module + (func $f32.no_fold_mul_divs (param $x f32) (param $y f32) (param $z f32) (param $w f32) (result f32) + (f32.mul (f32.div (get_local $x) (get_local $y)) (f32.div (get_local $z) (get_local $w)))) + (export "f32.no_fold_mul_divs" $f32.no_fold_mul_divs) + + (func $f64.no_fold_mul_divs (param $x f64) (param $y f64) (param $z f64) (param $w f64) (result f64) + (f64.mul (f64.div (get_local $x) (get_local $y)) (f64.div (get_local $z) (get_local $w)))) + (export "f64.no_fold_mul_divs" $f64.no_fold_mul_divs) +) + +(assert_return (invoke "f32.no_fold_mul_divs" (f32.const -0x1.c483bep-109) (f32.const 0x1.ee1c3cp-92) (f32.const 0x1.800756p-88) (f32.const -0x1.95b972p+4)) (f32.const 0x1.bbd30cp-110)) +(assert_return (invoke "f32.no_fold_mul_divs" (f32.const -0x1.0f4262p+102) (f32.const 0x1.248498p+25) (f32.const 0x1.f66a7cp-17) (f32.const 0x1.897fc8p-3)) (f32.const -0x1.2f1aa4p+63)) +(assert_return (invoke "f32.no_fold_mul_divs" (f32.const -0x1.df5f22p+33) (f32.const -0x1.fcee3ep+39) (f32.const -0x1.9ea914p+29) (f32.const -0x1.2c4d3p+10)) (f32.const 0x1.4cf51cp+13)) +(assert_return (invoke "f32.no_fold_mul_divs" (f32.const -0x1.f568bcp+109) (f32.const 0x1.d9963p-34) (f32.const 0x1.37a87ap-16) (f32.const 0x1.a1524ap+78)) (f32.const -infinity)) +(assert_return (invoke "f32.no_fold_mul_divs" (f32.const 0x1.3dd592p-53) (f32.const -0x1.332c22p-64) (f32.const 0x1.b01064p-91) (f32.const 0x1.92bb3ap-36)) (f32.const -0x1.1c2dbp-44)) + +(assert_return (invoke "f64.no_fold_mul_divs" (f64.const -0x1.363d6764f7b12p-819) (f64.const -0x1.ed5471f660b5fp-464) (f64.const -0x1.671b0a7f3a42p+547) (f64.const 0x1.0633be34ba1f2p+186)) (f64.const -0x1.b8fa2b76baeebp+5)) +(assert_return (invoke "f64.no_fold_mul_divs" (f64.const -0x1.37880182e0fa8p+115) (f64.const 0x1.f842631576147p-920) (f64.const -0x1.999372231d156p+362) (f64.const -0x1.d5db481ab9554p+467)) (f64.const -infinity)) +(assert_return (invoke "f64.no_fold_mul_divs" (f64.const -0x1.9a747c8d4b541p+308) (f64.const -0x1.99092ad6bbdc8p+192) (f64.const -0x1.cb23755c20101p-140) (f64.const -0x1.de8716f6b0b6ap+732)) (f64.const 0x1.ecf584c8466a5p-757)) +(assert_return (invoke "f64.no_fold_mul_divs" (f64.const -0x1.c424b2ece903dp+129) (f64.const -0x1.568ce281db37fp-347) (f64.const 0x1.53900b99fd3dp-957) (f64.const 0x1.5c33952254dadp+223)) (f64.const 0x0p+0)) +(assert_return (invoke "f64.no_fold_mul_divs" (f64.const 0x1.a8ec2cecb32a9p-18) (f64.const 0x1.58acab0051851p-277) (f64.const 0x1.35e87c9077f7fp-620) (f64.const -0x1.925ee37ffb386p+352)) (f64.const -0x1.e6286970b31bfp-714)) From 42b87937338d748d623342bcb761a697753dafdc Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 27 Apr 2016 07:14:27 -0700 Subject: [PATCH 25/31] Test that (x/z)+(y/z) is not optimized to (x+y)/z. --- ml-proto/test/float_exprs.wast | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/ml-proto/test/float_exprs.wast b/ml-proto/test/float_exprs.wast index fff762797c..84c2d3bf6a 100644 --- a/ml-proto/test/float_exprs.wast +++ b/ml-proto/test/float_exprs.wast @@ -1616,3 +1616,27 @@ (assert_return (invoke "f64.no_fold_mul_divs" (f64.const -0x1.9a747c8d4b541p+308) (f64.const -0x1.99092ad6bbdc8p+192) (f64.const -0x1.cb23755c20101p-140) (f64.const -0x1.de8716f6b0b6ap+732)) (f64.const 0x1.ecf584c8466a5p-757)) (assert_return (invoke "f64.no_fold_mul_divs" (f64.const -0x1.c424b2ece903dp+129) (f64.const -0x1.568ce281db37fp-347) (f64.const 0x1.53900b99fd3dp-957) (f64.const 0x1.5c33952254dadp+223)) (f64.const 0x0p+0)) (assert_return (invoke "f64.no_fold_mul_divs" (f64.const 0x1.a8ec2cecb32a9p-18) (f64.const 0x1.58acab0051851p-277) (f64.const 0x1.35e87c9077f7fp-620) (f64.const -0x1.925ee37ffb386p+352)) (f64.const -0x1.e6286970b31bfp-714)) + +;; Test that (x/z)+(y/z) is not optimized to (x+y)/z. + +(module + (func $f32.no_fold_add_divs (param $x f32) (param $y f32) (param $z f32) (result f32) + (f32.add (f32.div (get_local $x) (get_local $z)) (f32.div (get_local $y) (get_local $z)))) + (export "f32.no_fold_add_divs" $f32.no_fold_add_divs) + + (func $f64.no_fold_add_divs (param $x f64) (param $y f64) (param $z f64) (result f64) + (f64.add (f64.div (get_local $x) (get_local $z)) (f64.div (get_local $y) (get_local $z)))) + (export "f64.no_fold_add_divs" $f64.no_fold_add_divs) +) + +(assert_return (invoke "f32.no_fold_add_divs" (f32.const 0x1.795e7p+8) (f32.const -0x1.48a5eep-5) (f32.const -0x1.9a244cp+126)) (f32.const -0x1.d709b6p-119)) +(assert_return (invoke "f32.no_fold_add_divs" (f32.const -0x1.ae89e8p-63) (f32.const -0x1.e9903ep-49) (f32.const -0x1.370a8cp+47)) (f32.const 0x1.92f3f6p-96)) +(assert_return (invoke "f32.no_fold_add_divs" (f32.const -0x1.626408p-46) (f32.const 0x1.2ee5b2p-64) (f32.const -0x1.ecefaap+48)) (f32.const 0x1.701864p-95)) +(assert_return (invoke "f32.no_fold_add_divs" (f32.const -0x1.061d3p-101) (f32.const 0x1.383492p-98) (f32.const -0x1.1d92d2p+88)) (f32.const 0x0p+0)) +(assert_return (invoke "f32.no_fold_add_divs" (f32.const 0x1.1ea39ep-10) (f32.const 0x1.a7fffep-3) (f32.const 0x1.6fc574p-123)) (f32.const 0x1.28b2dep+120)) + +(assert_return (invoke "f64.no_fold_add_divs" (f64.const -0x1.c5fcc3273b136p+430) (f64.const 0x1.892a09eed8f6fp+434) (f64.const 0x1.8258b71e64397p+911)) (f64.const 0x1.e36eb9706ad82p-478)) +(assert_return (invoke "f64.no_fold_add_divs" (f64.const -0x1.2215d4061b5b3p+53) (f64.const 0x1.fb6184d97f27cp+5) (f64.const -0x1.f3bb59dacc0ebp-957)) (f64.const 0x1.2934eb0118be3p+1009)) +(assert_return (invoke "f64.no_fold_add_divs" (f64.const -0x1.e7a4533741d8ep-967) (f64.const 0x1.a519bb7feb802p-976) (f64.const 0x1.1f8a43454e51ap+504)) (f64.const 0x0p+0)) +(assert_return (invoke "f64.no_fold_add_divs" (f64.const 0x1.991c6cf93e2b4p+313) (f64.const -0x1.f2f7432698d11p+329) (f64.const 0x1.0d8c1b2453617p-126)) (f64.const -0x1.d9e1d84ddd1d4p+455)) +(assert_return (invoke "f64.no_fold_add_divs" (f64.const -0x1.d436849dc1271p-728) (f64.const 0x1.19d1c1450e52dp-755) (f64.const 0x1.fa1be69ea06fep-70)) (f64.const -0x1.d9a9b1c2f5623p-659)) From 0d2a6ac1cd9b5977ceed724a5e2c34d2f850dda3 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 27 Apr 2016 07:14:29 -0700 Subject: [PATCH 26/31] Test that sqrt(x*x) is not optimized to abs(x). --- ml-proto/test/float_exprs.wast | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/ml-proto/test/float_exprs.wast b/ml-proto/test/float_exprs.wast index 84c2d3bf6a..e721811daf 100644 --- a/ml-proto/test/float_exprs.wast +++ b/ml-proto/test/float_exprs.wast @@ -1640,3 +1640,27 @@ (assert_return (invoke "f64.no_fold_add_divs" (f64.const -0x1.e7a4533741d8ep-967) (f64.const 0x1.a519bb7feb802p-976) (f64.const 0x1.1f8a43454e51ap+504)) (f64.const 0x0p+0)) (assert_return (invoke "f64.no_fold_add_divs" (f64.const 0x1.991c6cf93e2b4p+313) (f64.const -0x1.f2f7432698d11p+329) (f64.const 0x1.0d8c1b2453617p-126)) (f64.const -0x1.d9e1d84ddd1d4p+455)) (assert_return (invoke "f64.no_fold_add_divs" (f64.const -0x1.d436849dc1271p-728) (f64.const 0x1.19d1c1450e52dp-755) (f64.const 0x1.fa1be69ea06fep-70)) (f64.const -0x1.d9a9b1c2f5623p-659)) + +;; Test that sqrt(x*x) is not optimized to abs(x). + +(module + (func $f32.no_fold_sqrt_square (param $x f32) (result f32) + (f32.sqrt (f32.mul (get_local $x) (get_local $x)))) + (export "f32.no_fold_sqrt_square" $f32.no_fold_sqrt_square) + + (func $f64.no_fold_sqrt_square (param $x f64) (result f64) + (f64.sqrt (f64.mul (get_local $x) (get_local $x)))) + (export "f64.no_fold_sqrt_square" $f64.no_fold_sqrt_square) +) + +(assert_return (invoke "f32.no_fold_sqrt_square" (f32.const -0x1.5cb316p-66)) (f32.const 0x1.5cb322p-66)) +(assert_return (invoke "f32.no_fold_sqrt_square" (f32.const -0x1.b0f9e4p-73)) (f32.const 0x1.b211b2p-73)) +(assert_return (invoke "f32.no_fold_sqrt_square" (f32.const -0x1.de417cp-71)) (f32.const 0x1.de65b8p-71)) +(assert_return (invoke "f32.no_fold_sqrt_square" (f32.const 0x1.64c872p-86)) (f32.const 0x0p+0)) +(assert_return (invoke "f32.no_fold_sqrt_square" (f32.const 0x1.e199e4p+108)) (f32.const infinity)) + +(assert_return (invoke "f64.no_fold_sqrt_square" (f64.const 0x1.1759d657203fdp-529)) (f64.const 0x1.1759dd57545f3p-529)) +(assert_return (invoke "f64.no_fold_sqrt_square" (f64.const -0x1.4c68de1c78d83p-514)) (f64.const 0x1.4c68de1c78d81p-514)) +(assert_return (invoke "f64.no_fold_sqrt_square" (f64.const -0x1.214736edb6e1ep-521)) (f64.const 0x1.214736ed9cf8dp-521)) +(assert_return (invoke "f64.no_fold_sqrt_square" (f64.const -0x1.0864b9f68457p-616)) (f64.const 0x0p+0)) +(assert_return (invoke "f64.no_fold_sqrt_square" (f64.const 0x1.b2a9855995abap+856)) (f64.const infinity)) From 34fd727e549229e7f4392e5940ee927044a912f5 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 27 Apr 2016 07:14:30 -0700 Subject: [PATCH 27/31] Test that sqrt(x)*sqrt(y) is not optimized to sqrt(x*y). --- ml-proto/test/float_exprs.wast | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/ml-proto/test/float_exprs.wast b/ml-proto/test/float_exprs.wast index e721811daf..68b0f4c0f1 100644 --- a/ml-proto/test/float_exprs.wast +++ b/ml-proto/test/float_exprs.wast @@ -1664,3 +1664,27 @@ (assert_return (invoke "f64.no_fold_sqrt_square" (f64.const -0x1.214736edb6e1ep-521)) (f64.const 0x1.214736ed9cf8dp-521)) (assert_return (invoke "f64.no_fold_sqrt_square" (f64.const -0x1.0864b9f68457p-616)) (f64.const 0x0p+0)) (assert_return (invoke "f64.no_fold_sqrt_square" (f64.const 0x1.b2a9855995abap+856)) (f64.const infinity)) + +;; Test that sqrt(x)*sqrt(y) is not optimized to sqrt(x*y). + +(module + (func $f32.no_fold_mul_sqrts (param $x f32) (param $y f32) (result f32) + (f32.mul (f32.sqrt (get_local $x)) (f32.sqrt (get_local $y)))) + (export "f32.no_fold_mul_sqrts" $f32.no_fold_mul_sqrts) + + (func $f64.no_fold_mul_sqrts (param $x f64) (param $y f64) (result f64) + (f64.mul (f64.sqrt (get_local $x)) (f64.sqrt (get_local $y)))) + (export "f64.no_fold_mul_sqrts" $f64.no_fold_mul_sqrts) +) + +(assert_return_nan (invoke "f32.no_fold_mul_sqrts" (f32.const 0x1.dddda8p-125) (f32.const -0x1.25d22ap-83))) +(assert_return (invoke "f32.no_fold_mul_sqrts" (f32.const 0x1.418d14p-92) (f32.const 0x1.c6535cp-32)) (f32.const 0x1.7e373ap-62)) +(assert_return (invoke "f32.no_fold_mul_sqrts" (f32.const 0x1.4de7ep-88) (f32.const 0x1.84ff18p+6)) (f32.const 0x1.686668p-41)) +(assert_return (invoke "f32.no_fold_mul_sqrts" (f32.const 0x1.78091ep+101) (f32.const 0x1.81feb8p-9)) (f32.const 0x1.7cfb98p+46)) +(assert_return (invoke "f32.no_fold_mul_sqrts" (f32.const 0x1.583ap-56) (f32.const 0x1.14ba2ap-9)) (f32.const 0x1.b47a8ep-33)) + +(assert_return_nan (invoke "f64.no_fold_mul_sqrts" (f64.const -0x1.d1144cc28cdbep-635) (f64.const -0x1.bf9bc373d3b6ap-8))) +(assert_return (invoke "f64.no_fold_mul_sqrts" (f64.const 0x1.5a7eb976bebc9p-643) (f64.const 0x1.f30cb8865a4cap-404)) (f64.const 0x1.260a1032d6e76p-523)) +(assert_return (invoke "f64.no_fold_mul_sqrts" (f64.const 0x1.711a0c1707935p-89) (f64.const 0x1.6fb5de51a20d3p-913)) (f64.const 0x1.7067ca28e31ecp-501)) +(assert_return (invoke "f64.no_fold_mul_sqrts" (f64.const 0x1.fb0bbea33b076p-363) (f64.const 0x1.d963b34894158p-573)) (f64.const 0x1.e9edc1fa624afp-468)) +(assert_return (invoke "f64.no_fold_mul_sqrts" (f64.const 0x1.8676eab7a4d0dp+24) (f64.const 0x1.75a58231ba7a5p+513)) (f64.const 0x1.0e16aebe203b3p+269)) From 8cc515e708b7ffcc59667b44421eceb9d0af249c Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 27 Apr 2016 07:14:32 -0700 Subject: [PATCH 28/31] Test that sqrt(x)/sqrt(y) is not optimized to sqrt(x/y). --- ml-proto/test/float_exprs.wast | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/ml-proto/test/float_exprs.wast b/ml-proto/test/float_exprs.wast index 68b0f4c0f1..1b2c637608 100644 --- a/ml-proto/test/float_exprs.wast +++ b/ml-proto/test/float_exprs.wast @@ -1688,3 +1688,27 @@ (assert_return (invoke "f64.no_fold_mul_sqrts" (f64.const 0x1.711a0c1707935p-89) (f64.const 0x1.6fb5de51a20d3p-913)) (f64.const 0x1.7067ca28e31ecp-501)) (assert_return (invoke "f64.no_fold_mul_sqrts" (f64.const 0x1.fb0bbea33b076p-363) (f64.const 0x1.d963b34894158p-573)) (f64.const 0x1.e9edc1fa624afp-468)) (assert_return (invoke "f64.no_fold_mul_sqrts" (f64.const 0x1.8676eab7a4d0dp+24) (f64.const 0x1.75a58231ba7a5p+513)) (f64.const 0x1.0e16aebe203b3p+269)) + +;; Test that sqrt(x)/sqrt(y) is not optimized to sqrt(x/y). + +(module + (func $f32.no_fold_div_sqrts (param $x f32) (param $y f32) (result f32) + (f32.div (f32.sqrt (get_local $x)) (f32.sqrt (get_local $y)))) + (export "f32.no_fold_div_sqrts" $f32.no_fold_div_sqrts) + + (func $f64.no_fold_div_sqrts (param $x f64) (param $y f64) (result f64) + (f64.div (f64.sqrt (get_local $x)) (f64.sqrt (get_local $y)))) + (export "f64.no_fold_div_sqrts" $f64.no_fold_div_sqrts) +) + +(assert_return_nan (invoke "f32.no_fold_div_sqrts" (f32.const -0x1.bea9bap+25) (f32.const -0x1.db776ep-58))) +(assert_return (invoke "f32.no_fold_div_sqrts" (f32.const 0x1.b983b6p+32) (f32.const 0x1.901f1ep+27)) (f32.const 0x1.7c4df6p+2)) +(assert_return (invoke "f32.no_fold_div_sqrts" (f32.const 0x1.d45e72p-120) (f32.const 0x1.ab49ccp+15)) (f32.const 0x1.7b0b04p-68)) +(assert_return (invoke "f32.no_fold_div_sqrts" (f32.const 0x1.b2e444p+59) (f32.const 0x1.5b8b16p-30)) (f32.const 0x1.94fca8p+44)) +(assert_return (invoke "f32.no_fold_div_sqrts" (f32.const 0x1.835aa6p-112) (f32.const 0x1.d17128p-103)) (f32.const 0x1.4a468p-5)) + +(assert_return_nan (invoke "f64.no_fold_div_sqrts" (f64.const -0x1.509fc16411167p-711) (f64.const -0x1.9c4255f5d6517p-187))) +(assert_return (invoke "f64.no_fold_div_sqrts" (f64.const 0x1.b6897bddac76p-587) (f64.const 0x1.104578b4c91f3p+541)) (f64.const 0x1.44e4f21f26cc9p-564)) +(assert_return (invoke "f64.no_fold_div_sqrts" (f64.const 0x1.ac83451b08989p+523) (f64.const 0x1.8da575c6d12b8p-109)) (f64.const 0x1.09c003991ce17p+316)) +(assert_return (invoke "f64.no_fold_div_sqrts" (f64.const 0x1.bab7836456417p-810) (f64.const 0x1.1ff60d03ba607p+291)) (f64.const 0x1.c0e6c833bf657p-551)) +(assert_return (invoke "f64.no_fold_div_sqrts" (f64.const 0x1.a957816ad9515p-789) (f64.const 0x1.8c18a3a222ab1p+945)) (f64.const 0x1.0948539781e92p-867)) From 15f44017a9b8c3044896aac9f1d95b318b8cf17b Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 27 Apr 2016 07:14:39 -0700 Subject: [PATCH 29/31] Test that (x*sqrt(y))/y is not optimized to x/sqrt(y). --- ml-proto/test/float_exprs.wast | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/ml-proto/test/float_exprs.wast b/ml-proto/test/float_exprs.wast index 1b2c637608..6d99091101 100644 --- a/ml-proto/test/float_exprs.wast +++ b/ml-proto/test/float_exprs.wast @@ -1712,3 +1712,27 @@ (assert_return (invoke "f64.no_fold_div_sqrts" (f64.const 0x1.ac83451b08989p+523) (f64.const 0x1.8da575c6d12b8p-109)) (f64.const 0x1.09c003991ce17p+316)) (assert_return (invoke "f64.no_fold_div_sqrts" (f64.const 0x1.bab7836456417p-810) (f64.const 0x1.1ff60d03ba607p+291)) (f64.const 0x1.c0e6c833bf657p-551)) (assert_return (invoke "f64.no_fold_div_sqrts" (f64.const 0x1.a957816ad9515p-789) (f64.const 0x1.8c18a3a222ab1p+945)) (f64.const 0x1.0948539781e92p-867)) + +;; Test that (x*sqrt(y))/y is not optimized to x/sqrt(y). + +(module + (func $f32.no_fold_mul_sqrt_div (param $x f32) (param $y f32) (result f32) + (f32.div (f32.mul (get_local $x) (f32.sqrt (get_local $y))) (get_local $y))) + (export "f32.no_fold_mul_sqrt_div" $f32.no_fold_mul_sqrt_div) + + (func $f64.no_fold_mul_sqrt_div (param $x f64) (param $y f64) (result f64) + (f64.div (f64.mul (get_local $x) (f64.sqrt (get_local $y))) (get_local $y))) + (export "f64.no_fold_mul_sqrt_div" $f64.no_fold_mul_sqrt_div) +) + +(assert_return (invoke "f32.no_fold_mul_sqrt_div" (f32.const -0x1.f4a7cap+81) (f32.const 0x1.c09adep+92)) (f32.const -infinity)) +(assert_return (invoke "f32.no_fold_mul_sqrt_div" (f32.const -0x1.90bf1cp-120) (f32.const 0x1.8dbe88p-97)) (f32.const -0x0p+0)) +(assert_return (invoke "f32.no_fold_mul_sqrt_div" (f32.const 0x1.8570e8p+29) (f32.const 0x1.217d3p-128)) (f32.const 0x1.6e391ap+93)) +(assert_return (invoke "f32.no_fold_mul_sqrt_div" (f32.const -0x1.5b4652p+43) (f32.const 0x1.a9d71cp+112)) (f32.const -0x1.0d423ap-13)) +(assert_return (invoke "f32.no_fold_mul_sqrt_div" (f32.const -0x1.910604p+8) (f32.const 0x1.0ca912p+7)) (f32.const -0x1.14cdecp+5)) + +(assert_return (invoke "f64.no_fold_mul_sqrt_div" (f64.const 0x1.1dcdeb857305fp+698) (f64.const 0x1.a066171c40eb9p+758)) (f64.const infinity)) +(assert_return (invoke "f64.no_fold_mul_sqrt_div" (f64.const -0x1.8b4f1c218e2abp-827) (f64.const 0x1.5e1ee65953b0bp-669)) (f64.const -0x0p+0)) +(assert_return (invoke "f64.no_fold_mul_sqrt_div" (f64.const 0x1.74ee531ddba38p-425) (f64.const 0x1.f370f758857f3p+560)) (f64.const 0x1.0aff34269583ep-705)) +(assert_return (invoke "f64.no_fold_mul_sqrt_div" (f64.const -0x1.27f216b0da6c5p+352) (f64.const 0x1.8e0b4e0b9fd7ep-483)) (f64.const -0x1.4fa558aad514ep+593)) +(assert_return (invoke "f64.no_fold_mul_sqrt_div" (f64.const 0x1.4c6955df9912bp+104) (f64.const 0x1.0cca42c9d371ep+842)) (f64.const 0x1.4468072f54294p-317)) From dafc31e4840306e24b2aa881b50b396fb52837d8 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 5 May 2016 14:57:04 -0700 Subject: [PATCH 30/31] Fix spello. --- ml-proto/test/float_exprs.wast | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ml-proto/test/float_exprs.wast b/ml-proto/test/float_exprs.wast index 6d99091101..1b16c157a4 100644 --- a/ml-proto/test/float_exprs.wast +++ b/ml-proto/test/float_exprs.wast @@ -1271,7 +1271,7 @@ (assert_return (invoke "llvm_pr27153" (i32.const 33554434)) (f32.const 25165824.000000)) -;; Test that (float)x + (float)y is not optimzied to (float)(x + y) when unsafe. +;; Test that (float)x + (float)y is not optimized to (float)(x + y) when unsafe. ;; https://llvm.org/bugs/show_bug.cgi?id=27036 (module From da9ec456fec2a9e5db311cc9d9cd5159b767d1b0 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 5 May 2016 14:58:53 -0700 Subject: [PATCH 31/31] Correct a function name to match the test. --- ml-proto/test/float_exprs.wast | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ml-proto/test/float_exprs.wast b/ml-proto/test/float_exprs.wast index 1b16c157a4..322a1960d5 100644 --- a/ml-proto/test/float_exprs.wast +++ b/ml-proto/test/float_exprs.wast @@ -1279,10 +1279,10 @@ (f32.add (f32.convert_s/i32 (i32.or (get_local $x) (i32.const -25034805))) (f32.convert_s/i32 (i32.and (get_local $y) (i32.const 14942208)))) ) - (export "llvm_pr27936" $llvm_pr27036) + (export "llvm_pr27036" $llvm_pr27036) ) -(assert_return (invoke "llvm_pr27936" (i32.const -25034805) (i32.const 14942208)) (f32.const -0x1.340068p+23)) +(assert_return (invoke "llvm_pr27036" (i32.const -25034805) (i32.const 14942208)) (f32.const -0x1.340068p+23)) ;; Test for bugs in old versions of historic IEEE 754 platforms as reported in: ;;