Browse Source
`fmin`/`fmax` are defined as returning -0.0 as smaller than 0.0. This is not how the IEEE754 views these values and the interpreter was returning the wrong value in these operations since it was just using the standard IEEE754 comparisons. This also tries to preserve NaN information by avoiding passing NaN's through any operation that could canonicalize it.pull/4388/head
Afonso Bordado
2 years ago
committed by
GitHub
5 changed files with 263 additions and 10 deletions
@ -0,0 +1,105 @@ |
|||||
|
test interpret |
||||
|
test run |
||||
|
target x86_64 |
||||
|
target aarch64 |
||||
|
target s390x |
||||
|
|
||||
|
function %fmax_f32(f32, f32) -> f32 { |
||||
|
block0(v0: f32, v1: f32): |
||||
|
v2 = fmax v0, v1 |
||||
|
return v2 |
||||
|
} |
||||
|
; run: %fmax_f32(0x1.0, 0x2.0) == 0x2.0 |
||||
|
; run: %fmax_f32(0x1.0p10, 0x1.0p11) == 0x1.0p11 |
||||
|
|
||||
|
; run: %fmax_f32(0x0.0, -0x0.0) == 0x0.0 |
||||
|
; run: %fmax_f32(-0x0.0, 0x0.0) == 0x0.0 |
||||
|
; run: %fmax_f32(+Inf, 0x0.0) == +Inf |
||||
|
; run: %fmax_f32(0x0.0, +Inf) == +Inf |
||||
|
; run: %fmax_f32(-Inf, 0x0.0) == 0x0.0 |
||||
|
; run: %fmax_f32(0x0.0, -Inf) == 0x0.0 |
||||
|
; run: %fmax_f32(+Inf, -Inf) == +Inf |
||||
|
|
||||
|
; F32 Epsilon / Max / Min Positive |
||||
|
; run: %fmax_f32(0x1.000002p-23, 0x1.000000p-23) == 0x1.000002p-23 |
||||
|
; run: %fmax_f32(0x1.fffffcp127, 0x1.fffffep127) == 0x1.fffffep127 |
||||
|
; run: %fmax_f32(0x1.000000p-126, 0x1.000000p-126) == 0x1.000000p-126 |
||||
|
|
||||
|
; F32 Subnormals |
||||
|
; run: %fmax_f32(0x0.800002p-126, 0x0.800000p-126) == 0x0.800002p-126 |
||||
|
; run: %fmax_f32(-0x0.800002p-126, -0x0.800000p-126) == -0x0.800000p-126 |
||||
|
|
||||
|
; F32 NaN's |
||||
|
; For NaN's this operation is specified as producing a value that is a NaN |
||||
|
; This behaviour differs from IEEE754's behaviour |
||||
|
function %fmax_is_nan_f32(f32, f32) -> i32 { |
||||
|
block0(v0: f32, v1: f32): |
||||
|
v2 = fmax v0, v1 |
||||
|
v3 = fcmp ne v2, v2 |
||||
|
v4 = bint.i32 v3 |
||||
|
return v4 |
||||
|
} |
||||
|
; run: %fmax_is_nan_f32(0x0.0, +NaN) == 1 |
||||
|
; run: %fmax_is_nan_f32(-NaN, 0x0.0) == 1 |
||||
|
; run: %fmax_is_nan_f32(0x0.0, +NaN:0x0) == 1 |
||||
|
; run: %fmax_is_nan_f32(0x0.0, +NaN:0x1) == 1 |
||||
|
; run: %fmax_is_nan_f32(0x0.0, +NaN:0x300001) == 1 |
||||
|
; run: %fmax_is_nan_f32(-NaN:0x0, 0x0.0) == 1 |
||||
|
; run: %fmax_is_nan_f32(-NaN:0x1, 0x0.0) == 1 |
||||
|
; run: %fmax_is_nan_f32(-NaN:0x300001, 0x0.0) == 1 |
||||
|
; run: %fmax_is_nan_f32(0x0.0, +sNaN:0x1) == 1 |
||||
|
; run: %fmax_is_nan_f32(-sNaN:0x1, 0x0.0) == 1 |
||||
|
; run: %fmax_is_nan_f32(0x0.0, +sNaN:0x200001) == 1 |
||||
|
; run: %fmax_is_nan_f32(-sNaN:0x200001, 0x0.0) == 1 |
||||
|
|
||||
|
|
||||
|
|
||||
|
function %fmax_f64(f64, f64) -> f64 { |
||||
|
block0(v0: f64, v1: f64): |
||||
|
v2 = fmax v0, v1 |
||||
|
return v2 |
||||
|
} |
||||
|
; run: %fmax_f64(0x1.0, 0x2.0) == 0x2.0 |
||||
|
; run: %fmax_f64(0x1.0p10, 0x1.0p11) == 0x1.0p11 |
||||
|
|
||||
|
; run: %fmax_f64(0x0.0, -0x0.0) == 0x0.0 |
||||
|
; run: %fmax_f64(-0x0.0, 0x0.0) == 0x0.0 |
||||
|
; run: %fmax_f64(+Inf, 0x0.0) == +Inf |
||||
|
; run: %fmax_f64(0x0.0, +Inf) == +Inf |
||||
|
; run: %fmax_f64(-Inf, 0x0.0) == 0x0.0 |
||||
|
; run: %fmax_f64(0x0.0, -Inf) == 0x0.0 |
||||
|
; run: %fmax_f64(+Inf, -Inf) == +Inf |
||||
|
|
||||
|
; F64 Epsilon / Max / Min Positive |
||||
|
; run: %fmax_f64(0x1.0000000000002p-52, 0x1.0000000000000p-52) == 0x1.0000000000002p-52 |
||||
|
; run: %fmax_f64(0x1.ffffffffffffcp1023, 0x1.fffffffffffffp1023) == 0x1.fffffffffffffp1023 |
||||
|
; run: %fmax_f64(0x1.0000000000000p-1022, 0x1.0000000000000p-1022) == 0x1.0000000000000p-1022 |
||||
|
|
||||
|
; F64 Subnormals |
||||
|
; run: %fmax_f64(0x0.8000000000002p-1022, 0x0.8000000000000p-1022) == 0x0.8000000000002p-1022 |
||||
|
; run: %fmax_f64(-0x0.8000000000002p-1022, -0x0.8000000000000p-1022) == -0x0.8000000000000p-1022 |
||||
|
|
||||
|
|
||||
|
|
||||
|
; F64 NaN's |
||||
|
; For NaN's this operation is specified as producing a value that is a NaN |
||||
|
; This behaviour differs from IEEE754's behaviour |
||||
|
function %fmax_is_nan_f64(f64, f64) -> i32 { |
||||
|
block0(v0: f64, v1: f64): |
||||
|
v2 = fmax v0, v1 |
||||
|
v3 = fcmp ne v2, v2 |
||||
|
v4 = bint.i32 v3 |
||||
|
return v4 |
||||
|
} |
||||
|
; run: %fmax_is_nan_f64(0x0.0, +NaN) == 1 |
||||
|
; run: %fmax_is_nan_f64(-NaN, 0x0.0) == 1 |
||||
|
; run: %fmax_is_nan_f64(0x0.0, +NaN:0x0) == 1 |
||||
|
; run: %fmax_is_nan_f64(0x0.0, +NaN:0x1) == 1 |
||||
|
; run: %fmax_is_nan_f64(0x0.0, +NaN:0x4000000000001) == 1 |
||||
|
; run: %fmax_is_nan_f64(-NaN:0x0, 0x0.0) == 1 |
||||
|
; run: %fmax_is_nan_f64(-NaN:0x1, 0x0.0) == 1 |
||||
|
; run: %fmax_is_nan_f64(-NaN:0x4000000000001, 0x0.0) == 1 |
||||
|
; run: %fmax_is_nan_f64(0x0.0, +sNaN:0x1) == 1 |
||||
|
; run: %fmax_is_nan_f64(-sNaN:0x1, 0x0.0) == 1 |
||||
|
; run: %fmax_is_nan_f64(0x0.0, +sNaN:0x4000000000001) == 1 |
||||
|
; run: %fmax_is_nan_f64(-sNaN:0x4000000000001, 0x0.0) == 1 |
@ -0,0 +1,105 @@ |
|||||
|
test interpret |
||||
|
test run |
||||
|
target x86_64 |
||||
|
target aarch64 |
||||
|
target s390x |
||||
|
|
||||
|
function %fmin_f32(f32, f32) -> f32 { |
||||
|
block0(v0: f32, v1: f32): |
||||
|
v2 = fmin v0, v1 |
||||
|
return v2 |
||||
|
} |
||||
|
; run: %fmin_f32(0x1.0, 0x2.0) == 0x1.0 |
||||
|
; run: %fmin_f32(0x1.0p10, 0x1.0p11) == 0x1.0p10 |
||||
|
|
||||
|
; run: %fmin_f32(0x0.0, -0x0.0) == -0x0.0 |
||||
|
; run: %fmin_f32(-0x0.0, 0x0.0) == -0x0.0 |
||||
|
; run: %fmin_f32(+Inf, 0x0.0) == 0x0.0 |
||||
|
; run: %fmin_f32(0x0.0, +Inf) == 0x0.0 |
||||
|
; run: %fmin_f32(-Inf, 0x0.0) == -Inf |
||||
|
; run: %fmin_f32(0x0.0, -Inf) == -Inf |
||||
|
; run: %fmin_f32(+Inf, -Inf) == -Inf |
||||
|
|
||||
|
; F32 Epsilon / Max / Min Positive |
||||
|
; run: %fmin_f32(0x1.000002p-23, 0x1.000000p-23) == 0x1.000000p-23 |
||||
|
; run: %fmin_f32(0x1.fffffcp127, 0x1.fffffep127) == 0x1.fffffcp127 |
||||
|
; run: %fmin_f32(0x1.000000p-126, 0x1.000000p-126) == 0x1.000000p-126 |
||||
|
|
||||
|
; F32 Subnormals |
||||
|
; run: %fmin_f32(0x0.800002p-126, 0x0.800000p-126) == 0x0.800000p-126 |
||||
|
; run: %fmin_f32(-0x0.800002p-126, -0x0.800000p-126) == -0x0.800002p-126 |
||||
|
|
||||
|
; F32 NaN's |
||||
|
; For NaN's this operation is specified as producing a value that is a NaN |
||||
|
; This behaviour differs from IEEE754's behaviour |
||||
|
function %fmin_is_nan_f32(f32, f32) -> i32 { |
||||
|
block0(v0: f32, v1: f32): |
||||
|
v2 = fmin v0, v1 |
||||
|
v3 = fcmp ne v2, v2 |
||||
|
v4 = bint.i32 v3 |
||||
|
return v4 |
||||
|
} |
||||
|
; run: %fmin_is_nan_f32(0x0.0, +NaN) == 1 |
||||
|
; run: %fmin_is_nan_f32(-NaN, 0x0.0) == 1 |
||||
|
; run: %fmin_is_nan_f32(0x0.0, +NaN:0x0) == 1 |
||||
|
; run: %fmin_is_nan_f32(0x0.0, +NaN:0x1) == 1 |
||||
|
; run: %fmin_is_nan_f32(0x0.0, +NaN:0x300001) == 1 |
||||
|
; run: %fmin_is_nan_f32(-NaN:0x0, 0x0.0) == 1 |
||||
|
; run: %fmin_is_nan_f32(-NaN:0x1, 0x0.0) == 1 |
||||
|
; run: %fmin_is_nan_f32(-NaN:0x300001, 0x0.0) == 1 |
||||
|
; run: %fmin_is_nan_f32(0x0.0, +sNaN:0x1) == 1 |
||||
|
; run: %fmin_is_nan_f32(-sNaN:0x1, 0x0.0) == 1 |
||||
|
; run: %fmin_is_nan_f32(0x0.0, +sNaN:0x200001) == 1 |
||||
|
; run: %fmin_is_nan_f32(-sNaN:0x200001, 0x0.0) == 1 |
||||
|
|
||||
|
|
||||
|
|
||||
|
function %fmin_f64(f64, f64) -> f64 { |
||||
|
block0(v0: f64, v1: f64): |
||||
|
v2 = fmin v0, v1 |
||||
|
return v2 |
||||
|
} |
||||
|
; run: %fmin_f64(0x1.0, 0x2.0) == 0x1.0 |
||||
|
; run: %fmin_f64(0x1.0p10, 0x1.0p11) == 0x1.0p10 |
||||
|
|
||||
|
; run: %fmin_f64(0x0.0, -0x0.0) == -0x0.0 |
||||
|
; run: %fmin_f64(-0x0.0, 0x0.0) == -0x0.0 |
||||
|
; run: %fmin_f64(+Inf, 0x0.0) == 0x0.0 |
||||
|
; run: %fmin_f64(0x0.0, +Inf) == 0x0.0 |
||||
|
; run: %fmin_f64(-Inf, 0x0.0) == -Inf |
||||
|
; run: %fmin_f64(0x0.0, -Inf) == -Inf |
||||
|
; run: %fmin_f64(+Inf, -Inf) == -Inf |
||||
|
|
||||
|
; F64 Epsilon / Max / Min Positive |
||||
|
; run: %fmin_f64(0x1.0000000000002p-52, 0x1.0000000000000p-52) == 0x1.0000000000000p-52 |
||||
|
; run: %fmin_f64(0x1.ffffffffffffcp1023, 0x1.fffffffffffffp1023) == 0x1.ffffffffffffcp1023 |
||||
|
; run: %fmin_f64(0x1.0000000000000p-1022, 0x1.0000000000000p-1022) == 0x1.0000000000000p-1022 |
||||
|
|
||||
|
; F64 Subnormals |
||||
|
; run: %fmin_f64(0x0.8000000000002p-1022, 0x0.8000000000000p-1022) == 0x0.8000000000000p-1022 |
||||
|
; run: %fmin_f64(-0x0.8000000000002p-1022, -0x0.8000000000000p-1022) == -0x0.8000000000002p-1022 |
||||
|
|
||||
|
|
||||
|
|
||||
|
; F64 NaN's |
||||
|
; For NaN's this operation is specified as producing a value that is a NaN |
||||
|
; This behaviour differs from IEEE754's behaviour |
||||
|
function %fmin_is_nan_f64(f64, f64) -> i32 { |
||||
|
block0(v0: f64, v1: f64): |
||||
|
v2 = fmin v0, v1 |
||||
|
v3 = fcmp ne v2, v2 |
||||
|
v4 = bint.i32 v3 |
||||
|
return v4 |
||||
|
} |
||||
|
; run: %fmin_is_nan_f64(0x0.0, +NaN) == 1 |
||||
|
; run: %fmin_is_nan_f64(-NaN, 0x0.0) == 1 |
||||
|
; run: %fmin_is_nan_f64(0x0.0, +NaN:0x0) == 1 |
||||
|
; run: %fmin_is_nan_f64(0x0.0, +NaN:0x1) == 1 |
||||
|
; run: %fmin_is_nan_f64(0x0.0, +NaN:0x4000000000001) == 1 |
||||
|
; run: %fmin_is_nan_f64(-NaN:0x0, 0x0.0) == 1 |
||||
|
; run: %fmin_is_nan_f64(-NaN:0x1, 0x0.0) == 1 |
||||
|
; run: %fmin_is_nan_f64(-NaN:0x4000000000001, 0x0.0) == 1 |
||||
|
; run: %fmin_is_nan_f64(0x0.0, +sNaN:0x1) == 1 |
||||
|
; run: %fmin_is_nan_f64(-sNaN:0x1, 0x0.0) == 1 |
||||
|
; run: %fmin_is_nan_f64(0x0.0, +sNaN:0x4000000000001) == 1 |
||||
|
; run: %fmin_is_nan_f64(-sNaN:0x4000000000001, 0x0.0) == 1 |
Loading…
Reference in new issue