Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions system/lib/jsmath.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,3 @@ CALL_JS_2_TRIPLE(pow)
CALL_JS_1_IMPL_TRIPLE(round, {
return x >= 0 ? Math.floor(x + 0.5) : Math.ceil(x - 0.5);
})
CALL_JS_1_IMPL_TRIPLE(rint, {
function round(x) {
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;
})
Copy link
Member

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?

Copy link
Collaborator Author

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

Copy link
Collaborator Author

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

Copy link
Member

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...

Loading