Skip to content

Commit b463346

Browse files
authored
Add fast path for x % +/-1.0 (AssemblyScript#1447)
1 parent 1355ae7 commit b463346

File tree

8 files changed

+176
-281
lines changed

8 files changed

+176
-281
lines changed

std/assembly/math.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1567,6 +1567,12 @@ export namespace NativeMath {
15671567
}
15681568

15691569
export function mod(x: f64, y: f64): f64 { // see: musl/src/math/fmod.c
1570+
if (builtin_abs<f64>(y) == 1.0) {
1571+
// x % 1, x % -1 ==> sign(x) * abs(x - 1.0 * trunc(x / 1.0))
1572+
// TODO: move this rule to compiler's optimization pass.
1573+
// It could be apply for any x % C_pot, where "C_pot" is pow of two const.
1574+
return builtin_copysign<f64>(x - builtin_trunc<f64>(x), x);
1575+
}
15701576
var ux = reinterpret<u64>(x);
15711577
var uy = reinterpret<u64>(y);
15721578
var ex = <i64>(ux >> 52 & 0x7FF);
@@ -2871,6 +2877,12 @@ export namespace NativeMathf {
28712877
}
28722878

28732879
export function mod(x: f32, y: f32): f32 { // see: musl/src/math/fmodf.c
2880+
if (builtin_abs<f32>(y) == 1.0) {
2881+
// x % 1, x % -1 ==> sign(x) * abs(x - 1.0 * trunc(x / 1.0))
2882+
// TODO: move this rule to compiler's optimization pass.
2883+
// It could be apply for any x % C_pot, where "C_pot" is pow of two const.
2884+
return builtin_copysign<f32>(x - builtin_trunc<f32>(x), x);
2885+
}
28742886
var ux = reinterpret<u32>(x);
28752887
var uy = reinterpret<u32>(y);
28762888
var ex = <i32>(ux >> 23 & 0xFF);

tests/compiler/binary.optimized.wat

Lines changed: 8 additions & 281 deletions
Original file line numberDiff line numberDiff line change
@@ -43,293 +43,20 @@
4343
local.get $2
4444
)
4545
(func $~lib/math/NativeMathf.mod (param $0 f32) (result f32)
46-
(local $1 i32)
47-
(local $2 i32)
48-
(local $3 i32)
49-
(local $4 i32)
5046
local.get $0
51-
i32.reinterpret_f32
52-
local.tee $1
53-
i32.const -2147483648
54-
i32.and
55-
local.set $4
56-
local.get $1
57-
i32.const 23
58-
i32.shr_u
59-
i32.const 255
60-
i32.and
61-
local.tee $2
62-
i32.const 255
63-
i32.eq
64-
if
65-
local.get $0
66-
local.get $0
67-
f32.div
68-
return
69-
end
70-
block $folding-inner0
71-
local.get $1
72-
i32.const 1
73-
i32.shl
74-
local.tee $3
75-
i32.const 2130706432
76-
i32.le_u
77-
if
78-
local.get $3
79-
i32.const 2130706432
80-
i32.eq
81-
br_if $folding-inner0
82-
local.get $0
83-
return
84-
end
85-
local.get $2
86-
if (result i32)
87-
local.get $1
88-
i32.const 8388607
89-
i32.and
90-
i32.const 8388608
91-
i32.or
92-
else
93-
local.get $1
94-
i32.const 1
95-
local.get $2
96-
local.get $1
97-
i32.const 9
98-
i32.shl
99-
i32.clz
100-
i32.sub
101-
local.tee $2
102-
i32.sub
103-
i32.shl
104-
end
105-
local.set $1
106-
loop $while-continue|0
107-
local.get $2
108-
i32.const 127
109-
i32.gt_s
110-
if
111-
local.get $1
112-
i32.const 8388608
113-
i32.ge_u
114-
if (result i32)
115-
local.get $1
116-
i32.const 8388608
117-
i32.eq
118-
br_if $folding-inner0
119-
local.get $1
120-
i32.const 8388608
121-
i32.sub
122-
else
123-
local.get $1
124-
end
125-
i32.const 1
126-
i32.shl
127-
local.set $1
128-
local.get $2
129-
i32.const 1
130-
i32.sub
131-
local.set $2
132-
br $while-continue|0
133-
end
134-
end
135-
local.get $1
136-
i32.const 8388608
137-
i32.ge_u
138-
if
139-
local.get $1
140-
i32.const 8388608
141-
i32.eq
142-
br_if $folding-inner0
143-
local.get $1
144-
i32.const 8388608
145-
i32.sub
146-
local.set $1
147-
end
148-
local.get $1
149-
local.get $1
150-
i32.const 8
151-
i32.shl
152-
i32.clz
153-
local.tee $3
154-
i32.shl
155-
local.set $1
156-
local.get $2
157-
local.get $3
158-
i32.sub
159-
local.tee $2
160-
i32.const 0
161-
i32.gt_s
162-
if (result i32)
163-
local.get $1
164-
i32.const 8388608
165-
i32.sub
166-
local.get $2
167-
i32.const 23
168-
i32.shl
169-
i32.or
170-
else
171-
local.get $1
172-
i32.const 1
173-
local.get $2
174-
i32.sub
175-
i32.shr_u
176-
end
177-
local.get $4
178-
i32.or
179-
f32.reinterpret_i32
180-
return
181-
end
182-
f32.const 0
18347
local.get $0
184-
f32.mul
48+
f32.trunc
49+
f32.sub
50+
local.get $0
51+
f32.copysign
18552
)
18653
(func $~lib/math/NativeMath.mod (param $0 f64) (result f64)
187-
(local $1 i64)
188-
(local $2 i64)
189-
(local $3 i64)
190-
(local $4 i64)
19154
local.get $0
192-
i64.reinterpret_f64
193-
local.tee $1
194-
i64.const 63
195-
i64.shr_u
196-
local.set $4
197-
local.get $1
198-
i64.const 52
199-
i64.shr_u
200-
i64.const 2047
201-
i64.and
202-
local.tee $2
203-
i64.const 2047
204-
i64.eq
205-
if
206-
local.get $0
207-
local.get $0
208-
f64.div
209-
return
210-
end
211-
block $folding-inner0
212-
local.get $1
213-
i64.const 1
214-
i64.shl
215-
local.tee $3
216-
i64.const 9214364837600034816
217-
i64.le_u
218-
if
219-
local.get $3
220-
i64.const 9214364837600034816
221-
i64.eq
222-
br_if $folding-inner0
223-
local.get $0
224-
return
225-
end
226-
local.get $2
227-
i64.eqz
228-
if (result i64)
229-
local.get $1
230-
i64.const 0
231-
local.get $2
232-
local.get $1
233-
i64.const 12
234-
i64.shl
235-
i64.clz
236-
i64.sub
237-
local.tee $2
238-
i64.sub
239-
i64.const 1
240-
i64.add
241-
i64.shl
242-
else
243-
local.get $1
244-
i64.const 4503599627370495
245-
i64.and
246-
i64.const 4503599627370496
247-
i64.or
248-
end
249-
local.set $1
250-
loop $while-continue|0
251-
local.get $2
252-
i64.const 1023
253-
i64.gt_s
254-
if
255-
local.get $1
256-
i64.const 4503599627370496
257-
i64.ge_u
258-
if (result i64)
259-
local.get $1
260-
i64.const 4503599627370496
261-
i64.eq
262-
br_if $folding-inner0
263-
local.get $1
264-
i64.const 4503599627370496
265-
i64.sub
266-
else
267-
local.get $1
268-
end
269-
i64.const 1
270-
i64.shl
271-
local.set $1
272-
local.get $2
273-
i64.const 1
274-
i64.sub
275-
local.set $2
276-
br $while-continue|0
277-
end
278-
end
279-
local.get $1
280-
i64.const 4503599627370496
281-
i64.ge_u
282-
if
283-
local.get $1
284-
i64.const 4503599627370496
285-
i64.eq
286-
br_if $folding-inner0
287-
local.get $1
288-
i64.const 4503599627370496
289-
i64.sub
290-
local.set $1
291-
end
292-
local.get $1
293-
local.get $1
294-
i64.const 11
295-
i64.shl
296-
i64.clz
297-
local.tee $3
298-
i64.shl
299-
local.set $1
300-
local.get $2
301-
local.get $3
302-
i64.sub
303-
local.tee $2
304-
i64.const 0
305-
i64.gt_s
306-
if (result i64)
307-
local.get $1
308-
i64.const 4503599627370496
309-
i64.sub
310-
local.get $2
311-
i64.const 52
312-
i64.shl
313-
i64.or
314-
else
315-
local.get $1
316-
i64.const 0
317-
local.get $2
318-
i64.sub
319-
i64.const 1
320-
i64.add
321-
i64.shr_u
322-
end
323-
local.get $4
324-
i64.const 63
325-
i64.shl
326-
i64.or
327-
f64.reinterpret_i64
328-
return
329-
end
330-
f64.const 0
33155
local.get $0
332-
f64.mul
56+
f64.trunc
57+
f64.sub
58+
local.get $0
59+
f64.copysign
33360
)
33461
(func $start:binary
33562
global.get $binary/i

tests/compiler/binary.untouched.wat

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1214,6 +1214,19 @@
12141214
(local $9 i32)
12151215
(local $10 i32)
12161216
(local $11 i32)
1217+
local.get $1
1218+
f32.abs
1219+
f32.const 1
1220+
f32.eq
1221+
if
1222+
local.get $0
1223+
local.get $0
1224+
f32.trunc
1225+
f32.sub
1226+
local.get $0
1227+
f32.copysign
1228+
return
1229+
end
12171230
local.get $0
12181231
i32.reinterpret_f32
12191232
local.set $2
@@ -2076,6 +2089,19 @@
20762089
(local $9 i64)
20772090
(local $10 i32)
20782091
(local $11 i64)
2092+
local.get $1
2093+
f64.abs
2094+
f64.const 1
2095+
f64.eq
2096+
if
2097+
local.get $0
2098+
local.get $0
2099+
f64.trunc
2100+
f64.sub
2101+
local.get $0
2102+
f64.copysign
2103+
return
2104+
end
20792105
local.get $0
20802106
i64.reinterpret_f64
20812107
local.set $2

0 commit comments

Comments
 (0)