[patch] Avoid boxing float/int32/int64 when doing direct call #5894
Original bug ID: 5894
Functions taking floating points parameters always receive them boxed.
This allow avoiding all allocations in a function like
let (+) = Nativeint.add
This patch take care of not unboxing parameters when it is possible that this
For instance a function like this
let bad (x:float) =
bad will not be specialised because its parameter is used boxed inside its body.
In a case like:
let rec f x y =
and g a b =
and h c d =
only the y parameter of f and a of g will be unboxed.
The return value will be unboxed if every possible returned value is unboxed.
x +. y is considered unboxed
is considered boxed because List.hd return an already boxed value.
The text was updated successfully, but these errors were encountered:
Comment author: @gasche
Have you tested the efficiency of this optimization on some of the float-heavy benchmark code that started flowing in (from Alain for example)?
It should be possible to have the boxed version just unbox, and then call the unboxed version; that would result in little additional compiled code. But this is only efficient if the inliner reliably removes this indirection layer (which amounts to unboxing at call-site).
Can the inliner be relied upon for this? How much does this degrade the performances in the case where no inlining can happen anyway (no .cmx, functor application...)?
(A way to work around the "not sure if boxing will be needed" problem is to specialize to a function that takes two arguments, the boxed and the unboxed data. This is better than the boxing version because you don't have to unbox at definition site, could actually not have much overhead if the unboxed data is passed efficiently, and guarantees that no additional allocation is necessary -- it's essentially a specialization of the technique of "On the runtime complexity of type-directed unboxing", Garrigue and Minamide, 1998. I don't expect it to work in practice, but you never know.)
Comment author: @alainfrisch
This is great news. I fully support this project!
I'm not sure this is a good criterion, although it is in line with the current intra-function behavior (don't unbox if there is a potential use site in boxed form). It could very well be the case that the parameter might be used boxed inside the body, but only in rare cases (e.g. to print an error message if some invariant is broken). If this disable the optimization, it means the caller might need to box the parameter.
Have you tried to combine your patch with the strategy I propose to deal with boxing (#5204), i.e. box "lazily" (on demand + memoization)?
Comment author: @chambart
On Alain's bench on my computer:
with patch (and a few forgoten cases present in my git branch):
Notice that more than half the running time is taken in __ieee754_exp
The majority of other float heavy benchmarks I encountered, where written with
I will update the patch with a few more things: function parameters
let f x = let a = if Random.bool () then x else x in a +.a
was compiled allocating x and loading from it.
This is fixed in my git branch:
testing it with opam:
opam remote add comp https://github.com/chambart/opam-compilers-repository.git
will generate a generic call to (+.) I have another patch in preparation
The main interest of avoiding boxing is to avoid some allocation, passing both
Off topic: How do I remove an attached file ? Is the bug reporter