Skip to content

Commit 3c2c6ee

Browse files
authored
[spec/test] Relax relaxed_trunc semantics (#1906)
1 parent c022fb1 commit 3c2c6ee

File tree

2 files changed

+7
-123
lines changed

2 files changed

+7
-123
lines changed

document/core/exec/numerics.rst

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2205,20 +2205,20 @@ The implementation-specific behaviour of this operation is determined by the glo
22052205
:math:`\relaxedtrunc^u_{M,N}(z)`
22062206
................................
22072207

2208-
The implementation-specific behaviour of this operation is determined by the global parameter :math:`R_{\F{trunc\_u}} \in \{0, 1, 2, 3\}`.
2208+
The implementation-specific behaviour of this operation is determined by the global parameter :math:`R_{\F{trunc\_u}} \in \{0, 1\}`.
22092209

22102210
* If :math:`z` is normal or subnormal and :math:`\trunc(z)` is non-negative and less than :math:`2^N`, then return :math:`\truncu_{M,N}(z)`.
22112211

2212-
* Else, return :math:`\relaxed(R_{\F{trunc\_u}})[ \truncsatu_{M,N}(z), 2^N-1, 2^N-2, 2^(N-1) ]`.
2212+
* Else, return :math:`\relaxed(R_{\F{trunc\_u}})[ \truncsatu_{M,N}(z), \mathbf{R} ]`.
22132213

22142214
.. math::
22152215
\begin{array}{@{}lcll}
22162216
\relaxedtrunc^u_{M,N}(\pm q) &=& \truncu_{M,N}(\pm q) & (\iff 0 \leq \trunc(\pm q) < 2^N) \\
2217-
\relaxedtrunc^u_{M,N}(z) &=& \relaxed(R_{\F{trunc\_u}})[ \truncsatu_{M,N}(z), 2^{N}-1, 2^{N}-2, 2^{N-1}] & (\otherwise) \\
2217+
\relaxedtrunc^u_{M,N}(z) &=& \relaxed(R_{\F{trunc\_u}})[ \truncsatu_{M,N}(z), \mathbf{R}] & (\otherwise) \\
22182218
\end{array}
22192219
22202220
.. note::
2221-
Relaxed unsigned truncation is implementation-dependent for NaNs and out-of-range values.
2221+
Relaxed unsigned truncation is non-deterministic for NaNs and out-of-range values.
22222222
In the :ref:`deterministic profile <profile-deterministic>`,
22232223
it behaves like regular :math:`\truncsatu`.
22242224

@@ -2232,16 +2232,16 @@ The implementation-specific behaviour of this operation is determined by the glo
22322232

22332233
* If :math:`z` is normal or subnormal and :math:`\trunc(z)` is greater than or equal to :math:`-2^{N-1}` and less than :math:`2^{N-1}`, then return :math:`\truncs_{M,N}(z)`.
22342234

2235-
* Else, return :math:`\relaxed(R_{\F{trunc\_s}})[ \truncsats_{M,N}(z), 2^N-1, 2^N-2, 2^(N-1) ]`.
2235+
* Else, return :math:`\relaxed(R_{\F{trunc\_s}})[ \truncsats_{M,N}(z), \mathbf{R} ]`.
22362236

22372237
.. math::
22382238
\begin{array}{@{}lcll}
22392239
\relaxedtrunc^s_{M,N}(\pm q) &=& \truncs_{M,N}(\pm q) & (\iff -2^{N-1} \leq \trunc(\pm q) < 2^{N-1}) \\
2240-
\relaxedtrunc^s_{M,N}(z) &=& \relaxed(R_{\F{trunc\_s}})[ \truncsats_{M,N}(z), \signed^{-1}_N(-2^{N-1})] & (\otherwise) \\
2240+
\relaxedtrunc^s_{M,N}(z) &=& \relaxed(R_{\F{trunc\_s}})[ \truncsats_{M,N}(z), \mathbf{R}] & (\otherwise) \\
22412241
\end{array}
22422242
22432243
.. note::
2244-
Relaxed signed truncation is implementation-dependent for NaNs and out-of-range values.
2244+
Relaxed signed truncation is non-deterministic for NaNs and out-of-range values.
22452245
In the :ref:`deterministic profile <profile-deterministic>`,
22462246
it behaves like regular :math:`\truncsats`.
22472247

Lines changed: 0 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -1,124 +1,8 @@
11
;; Tests for i32x4.relaxed_trunc_f32x4_s, i32x4.relaxed_trunc_f32x4_u, i32x4.relaxed_trunc_f64x2_s_zero, and i32x4.relaxed_trunc_f64x2_u_zero.
2-
;; `either` comes from https://github.com/WebAssembly/threads.
32

43
(module
54
(func (export "i32x4.relaxed_trunc_f32x4_s") (param v128) (result v128) (i32x4.relaxed_trunc_f32x4_s (local.get 0)))
65
(func (export "i32x4.relaxed_trunc_f32x4_u") (param v128) (result v128) (i32x4.relaxed_trunc_f32x4_u (local.get 0)))
76
(func (export "i32x4.relaxed_trunc_f64x2_s_zero") (param v128) (result v128) (i32x4.relaxed_trunc_f64x2_s_zero (local.get 0)))
87
(func (export "i32x4.relaxed_trunc_f64x2_u_zero") (param v128) (result v128) (i32x4.relaxed_trunc_f64x2_u_zero (local.get 0)))
9-
10-
(func (export "i32x4.relaxed_trunc_f32x4_s_cmp") (param v128) (result v128)
11-
(i32x4.eq
12-
(i32x4.relaxed_trunc_f32x4_s (local.get 0))
13-
(i32x4.relaxed_trunc_f32x4_s (local.get 0))))
14-
(func (export "i32x4.relaxed_trunc_f32x4_u_cmp") (param v128) (result v128)
15-
(i32x4.eq
16-
(i32x4.relaxed_trunc_f32x4_u (local.get 0))
17-
(i32x4.relaxed_trunc_f32x4_u (local.get 0))))
18-
(func (export "i32x4.relaxed_trunc_f64x2_s_zero_cmp") (param v128) (result v128)
19-
(i32x4.eq
20-
(i32x4.relaxed_trunc_f64x2_s_zero (local.get 0))
21-
(i32x4.relaxed_trunc_f64x2_s_zero (local.get 0))))
22-
(func (export "i32x4.relaxed_trunc_f64x2_u_zero_cmp") (param v128) (result v128)
23-
(i32x4.eq
24-
(i32x4.relaxed_trunc_f64x2_u_zero (local.get 0))
25-
(i32x4.relaxed_trunc_f64x2_u_zero (local.get 0))))
268
)
27-
28-
;; Test some edge cases around min/max to ensure that the instruction either
29-
;; saturates correctly or returns INT_MIN.
30-
;;
31-
;; Note, though, that INT_MAX itself is not tested. The value for INT_MAX is
32-
;; 2147483647 but that is not representable in a `f32` since it requires 31 bits
33-
;; when a f32 has only 24 bits available. This means that the closest integers
34-
;; to INT_MAX which can be represented are 2147483520 and 2147483648, meaning
35-
;; that the INT_MAX test case cannot be tested.
36-
(assert_return (invoke "i32x4.relaxed_trunc_f32x4_s"
37-
;; INT32_MIN <INT32_MIN >INT32_MAX
38-
(v128.const f32x4 -2147483648.0 -2147483904.0 2.0 2147483904.0))
39-
;; out of range -> saturate or INT32_MIN
40-
(either (v128.const i32x4 -2147483648 -2147483648 2 2147483647)
41-
(v128.const i32x4 -2147483648 -2147483648 2 -2147483648)))
42-
43-
(assert_return (invoke "i32x4.relaxed_trunc_f32x4_s"
44-
(v128.const f32x4 nan -nan nan:0x444444 -nan:0x444444))
45-
;; nans -> 0 or INT32_MIN
46-
(either (v128.const i32x4 0 0 0 0)
47-
(v128.const i32x4 0x80000000 0x80000000 0x80000000 0x80000000)))
48-
49-
(assert_return (invoke "i32x4.relaxed_trunc_f32x4_u"
50-
;; UINT32_MIN UINT32_MIN-1 <UINT32_MAX UINT32_MAX+1
51-
(v128.const f32x4 0 -1.0 4294967040.0 4294967296.0))
52-
;; out of range -> saturate or UINT32_MAX
53-
(either (v128.const i32x4 0 0 4294967040 0xffffffff)
54-
(v128.const i32x4 0 0xffffffff 4294967040 0xffffffff)))
55-
56-
(assert_return (invoke "i32x4.relaxed_trunc_f32x4_u"
57-
(v128.const f32x4 nan -nan nan:0x444444 -nan:0x444444))
58-
;; nans -> 0 or UINT32_MAX
59-
(either (v128.const i32x4 0 0 0 0)
60-
(v128.const i32x4 0xffffffff 0xffffffff 0xffffffff 0xffffffff)))
61-
62-
(assert_return (invoke "i32x4.relaxed_trunc_f64x2_s_zero"
63-
(v128.const f64x2 -2147483904.0 2147483904.0))
64-
;; out of range -> saturate or INT32_MIN
65-
(either (v128.const i32x4 -2147483648 2147483647 0 0)
66-
(v128.const i32x4 -2147483648 -2147483648 0 0)))
67-
68-
(assert_return (invoke "i32x4.relaxed_trunc_f64x2_s_zero"
69-
(v128.const f64x2 nan -nan))
70-
(either (v128.const i32x4 0 0 0 0)
71-
(v128.const i32x4 0x80000000 0x80000000 0 0)))
72-
73-
(assert_return (invoke "i32x4.relaxed_trunc_f64x2_u_zero"
74-
(v128.const f64x2 -1.0 4294967296.0))
75-
;; out of range -> saturate or UINT32_MAX
76-
(either (v128.const i32x4 0 0xffffffff 0 0)
77-
(v128.const i32x4 0xffffffff 0xffffffff 0 0)))
78-
79-
(assert_return (invoke "i32x4.relaxed_trunc_f64x2_u_zero"
80-
(v128.const f64x2 nan -nan))
81-
(either (v128.const i32x4 0 0 0 0)
82-
(v128.const i32x4 0 0 0xffffffff 0xffffffff)))
83-
84-
;; Check that multiple calls to the relaxed instruction with same inputs returns same results.
85-
86-
(assert_return (invoke "i32x4.relaxed_trunc_f32x4_s_cmp"
87-
;; INT32_MIN <INT32_MIN INT32_MAX >INT32_MAX
88-
(v128.const f32x4 -2147483648.0 -2147483904.0 2147483647.0 2147483904.0))
89-
;; out of range -> saturate or INT32_MIN
90-
(v128.const i32x4 -1 -1 -1 -1))
91-
92-
(assert_return (invoke "i32x4.relaxed_trunc_f32x4_s_cmp"
93-
(v128.const f32x4 nan -nan nan:0x444444 -nan:0x444444))
94-
;; nans -> 0 or INT32_MIN
95-
(v128.const i32x4 -1 -1 -1 -1))
96-
97-
(assert_return (invoke "i32x4.relaxed_trunc_f32x4_u_cmp"
98-
;; UINT32_MIN UINT32_MIN-1 <UINT32_MAX UINT32_MAX+1
99-
(v128.const f32x4 0 -1.0 4294967040.0 4294967296.0))
100-
;; out of range -> saturate or UINT32_MAX
101-
(v128.const i32x4 -1 -1 -1 -1))
102-
103-
(assert_return (invoke "i32x4.relaxed_trunc_f32x4_u_cmp"
104-
(v128.const f32x4 nan -nan nan:0x444444 -nan:0x444444))
105-
;; nans -> 0 or UINT32_MAX
106-
(v128.const i32x4 -1 -1 -1 -1))
107-
108-
(assert_return (invoke "i32x4.relaxed_trunc_f64x2_s_zero_cmp"
109-
(v128.const f64x2 -2147483904.0 2147483904.0))
110-
;; out of range -> saturate or INT32_MIN
111-
(v128.const i32x4 -1 -1 -1 -1))
112-
113-
(assert_return (invoke "i32x4.relaxed_trunc_f64x2_s_zero_cmp"
114-
(v128.const f64x2 nan -nan))
115-
(v128.const i32x4 -1 -1 -1 -1))
116-
117-
(assert_return (invoke "i32x4.relaxed_trunc_f64x2_u_zero_cmp"
118-
(v128.const f64x2 -1.0 4294967296.0))
119-
;; out of range -> saturate or UINT32_MAX
120-
(v128.const i32x4 -1 -1 -1 -1))
121-
122-
(assert_return (invoke "i32x4.relaxed_trunc_f64x2_u_zero_cmp"
123-
(v128.const f64x2 nan -nan))
124-
(v128.const i32x4 -1 -1 -1 -1))

0 commit comments

Comments
 (0)