-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Remove rint from jsmath library. NFC #23148
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
a08cb90 to
e1ae48e
Compare
e1ae48e to
ff9d30f
Compare
|
I updated this change to only effect |
We also use `__builtin_rint` (which lowers to a single f64.nearest instruction) when compiling the musl version of rint.c so there there is no need to use a JS call for this case.
ff9d30f to
a2a3fc7
Compare
| return x >= 0 ? Math.floor(x + 0.5) : Math.ceil(x - 0.5); | ||
| } | ||
| return (x - Math.floor(x) != .5) ? round(x) : round(x / 2) * 2; | ||
| }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I am not certain the new code is smaller, as unless I am doing something wrong, even though rint.c just does __builtin_rint, it doesn't turn into a single instruction. My testcase:
#include <emscripten.h>
int main(int argc, char **argv) {
double x = double(argc + 1000) / double(argc + 100);
return __builtin_rint(x);
}emcc -O3 --profiling leads to
(func $main (param $0 i32) (param $1 i32) (result i32)
(local $2 f64)
(if
(f64.lt
(f64.abs
(local.tee $2
(f64.nearest
(f64.div
(f64.convert_i32_s
(i32.add
(local.get $0)
(i32.const 1000)
)
)
(f64.convert_i32_s
(i32.add
(local.get $0)
(i32.const 100)
)
)
)
)
)
)
(f64.const 2147483648)
)
(then
(return
(i32.trunc_f64_s
(local.get $2)
)
)
)
)
(i32.const -2147483648)
)Ignoring the division etc., it looks like rint is not a single instruction but f64.nearest, abs, lt, trunc operations?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rint does compile to single instruction:
$ ar x ./cache/sysroot/lib/wasm64-emscripten/libc.a rint.o
$ wasm-objdump -d -r -x rint.o
...
000059 func[0] <rint>:
00005a: 20 00 | local.get 0
00005c: 9e | f64.nearest
00005d: 0b | end
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The rest of the complixity in your example I think comes from the conversion from double to int because your are returning and double from your main function.
If I do this I see the expected results:
$ cat test.c
extern double x;
int main(int argc, char **argv) {
x = __builtin_rint(x);
}
$ ./emcc -Os test.c -c
$ dump test.o
000043 func[0] <__main_argc_argv>:
000044: 41 00 | i32.const 0
000046: 41 00 | i32.const 0
000048: 2b 03 80 80 80 80 00 | f64.load 3 0
00004a: R_WASM_MEMORY_ADDR_LEB 1 <x>
00004f: 9e | f64.nearest
000050: 39 03 80 80 80 80 00 | f64.store 3 0
000052: R_WASM_MEMORY_ADDR_LEB 1 <x>
000057: 41 00 | i32.const 0
000059: 0b | end
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, you're right, I missed the other conversion, sorry...
We use `__builtin_rint` (which lowers to a single `f64.nearest` instruction) when compiling the musl version of `rint.c` so there there is no need to use a JS call for this case.
We use
__builtin_rint(which lowers to a singlef64.nearestinstruction) when compiling the musl version of
rint.cso there there isno need to use a JS call for this case.