Skip to content
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

Speed up generic comparisons of int backed types #34

Merged
merged 1 commit into from
Dec 3, 2019

Conversation

rixed
Copy link
Contributor

@rixed rixed commented Oct 15, 2019

By making the small ints type known to the compiler (via the "private"
keyword) it is able to generate much better code when comparing those
values.

Example:

if v < Uint8.one then print_string "foo"

used to be compiled into (amd64 arch):

73fe5: 48 8d 05 64 47 05 00 lea 0x54764(%rip),%rax # c8750 <caml_lessthan>
73fec: e8 bf 6e 06 00 callq daeb0 <caml_c_call>
73ff1: 4c 8d 1d f0 95 0c 00 lea 0xc95f0(%rip),%r11 # 13d5e8 <caml_young_ptr>
73ff8: 4d 8b 3b mov (%r11),%r15
73ffb: 48 83 f8 01 cmp $0x1,%rax
73fff: 74 1a je ...

whereas after that change the expensive call to C is avoided:

73fd6: 48 8b 5b 10 mov 0x10(%rbx),%rbx
73fda: 48 83 e3 55 and $0x55,%rbx
73fde: 48 8b 80 10 13 00 00 mov 0x1310(%rax),%rax
73fe5: 48 39 c3 cmp %rax,%rbx
73fe8: 7d 1a jge ...

Other consequences of using the private keyword:

  • Stdint will only be compatible with OCaml compiler >= 3.11, which I
    think is OK;
  • Users will be allowed to "cast" small ints values into int with the
    casting operator, yielding to weird values for signed types (since
    those are shifted), which I think is also acceptable.

By making the small ints type known to the compiler (via the "private"
keyword) it is able to generate much better code when comparing those
values.

Example:

  if v < Uint8.one then print_string "foo"

used to be compiled into (amd64 arch):

   73fe5:       48 8d 05 64 47 05 00    lea    0x54764(%rip),%rax        # c8750 <caml_lessthan>
   73fec:       e8 bf 6e 06 00          callq  daeb0 <caml_c_call>
   73ff1:       4c 8d 1d f0 95 0c 00    lea    0xc95f0(%rip),%r11        # 13d5e8 <caml_young_ptr>
   73ff8:       4d 8b 3b                mov    (%r11),%r15
   73ffb:       48 83 f8 01             cmp    $0x1,%rax
   73fff:       74 1a                   je     ...

whereas after that change the expensive call to C is avoided:

   73fd6:       48 8b 5b 10             mov    0x10(%rbx),%rbx
   73fda:       48 83 e3 55             and    $0x55,%rbx
   73fde:       48 8b 80 10 13 00 00    mov    0x1310(%rax),%rax
   73fe5:       48 39 c3                cmp    %rax,%rbx
   73fe8:       7d 1a                   jge    ...

Other consequences of using the private keyword:

- Stdint will only be compatible with OCaml compiler >= 3.11, which I
  think is OK;
- Users will be allowed to "cast" small ints values into int with the
  casting operator, yielding to weird values for signed types (since
  those are shifted), which I think is also acceptable.
@rixed
Copy link
Contributor Author

rixed commented Nov 18, 2019

Impatient yet friendly ping. Is there a problem with that patch?

@rgrinberg rgrinberg merged commit 14871d8 into andrenth:master Dec 3, 2019
@rgrinberg
Copy link
Collaborator

Patch looks very good. Thanks

rgrinberg added a commit to rgrinberg/opam-repository that referenced this pull request Dec 3, 2019
CHANGES:

* Speed up generic comparison of int backed types (andrenth/ocaml-stdint#34, @rixed)
* Port to dune (andrenth/ocaml-stdint#35, @Tuncer)
* Move to stdlib from pervasives (andrenth/ocaml-stdint#36, @Tuncer)
@rixed rixed deleted the private-types branch February 10, 2020 20:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants