This code is what OCaml needs to do in order to arithmetic in a function call. This isn't code for "just" x*x, but rather it's code for "multiply two ints passed into a function and return the product as an int".<p>Implementations like SBCL have a similar overhead <i>for a function call containing arithmetic</i>. However, if you're doing more arithmetic within the function, the bit shifts etc. are only done once as a part of the function's pre/postamble. In fact, fully unboxed 64-bit arithmetic with integers or floats can be done if these values aren't crossing function boundaries or into the garbage-collected heap. (The latter, a memory read/write, is way more costly than a bit shift anyway.)<p>The term of art is "inlining" or "open-coding" arithmetic. Raw arithmetic can be open-coded, but data formats must be respected across function call boundaries and in the heap. Therefore, if you inline the function containing the arithmetic, you eliminate the pre/postamble overhead too. This is the same as in C-like languages as well, it's just that their pre/postambles are different.<p>"Block" or "whole-program compilation" can also sometimes eliminate these extra instructions, at some modest expenses (compile wall clock time, implementation complexity, increased size of compilation units, multiple function entry points, modularity, etc.).<p>OCaml's built-in Flambda [1,2] is a project/technology that will automatically leverage some of the above techniques (especially inlining) to achieve higher performance.<p>[1] <a href="https://v2.ocaml.org/manual/flambda.html" rel="nofollow noreferrer">https://v2.ocaml.org/manual/flambda.html</a><p>[2] <a href="https://blog.janestreet.com/flambda/" rel="nofollow noreferrer">https://blog.janestreet.com/flambda/</a>
This top bit is used by the garbage collector for performance. OCaml's GC is light enough that it simply does not feel like it exists at all. Integers also do not cause allocations.<p>Jane Street's blog explains the reasoning in detail[0]<p>[0] <a href="https://blog.janestreet.com/what-is-gained-and-lost-with-63-bit-integers/" rel="nofollow noreferrer">https://blog.janestreet.com/what-is-gained-and-lost-with-63-...</a>
This is a better explanation: <a href="https://web.archive.org/web/20180403212547/https://caml.inria.fr/pub/ml-archives/caml-list/2004/07/e86a25aa6c6a6a7d08dd7eb50cfd5d52.fr.html" rel="nofollow noreferrer">https://web.archive.org/web/20180403212547/https://caml.inri...</a><p>You'd be better off measuring actual performance on real world tasks before inferring anything. Modern CPUs overlap execution of instructions very aggressively.
You can use fewer instructions if you tag integers with a zero (as SBCL does); then 2x * 2y = 4xy, which we only need to shift right one bit to get 4xy/2 i.e 2xy. But this takes a bit off your fixnum size, so you might shift an operand right, which also is just one instruction (as (2x/2) * 2y = x * 2y = 2xy).
I'm confused.<p>In OCaml, the type system is strong and statically typed, ergo the type of a value is known at compile-time.<p>So...why would it need to do this to check if the type is an integer?