Skip to content

[@inline never] attribute may be ignored #10993

@markghayden

Description

@markghayden

It seems functions marked as [@inline never] may be still be inlined in Ocaml 4.13.0.

The particular pattern where we noticed this was when you have ML code with a small "add" function that calls a "grow" function if no space is available. Being small, "add" may benefit from inlining. "grow" may be large and the uncommon case, so it may be best not to inline it. "grow" is an internal function and is not exported from the module.

Even if marked [@inline never], the "grow" function appears to be inlined to the "add" function (overriding the attribute). This makes some since because un-exported, single-use functions should normally benefit from inlining. However, when "add" is inlined, "grow" is carried along and also inlined, which may be undesirable.

A work-around appears to be to export "grow" from the module interface, which seems to prevent it from being inlined.

A test case is attached. A non-operational bucket.ml class and caller in test.ml. When "grow" is not in the bucket.mli, it gets inlined into the call-site for "add". When "grow" is in the bucket.mli, the "add" function is inlined but "grow" is not (the desired behavior). Of course, you should not have to break the abstraction to achieve this. You can examine the included test.s to see that the inlining of "grow" occurs at the "add" call-site in test.ml.

bucket.mli:

`type 'a t ;;

val add: 'a t -> 'a -> unit ;;

(* If this is uncommented the grow will not be included in the add function.
*)
(val grow: 'a t -> 'a -> unit ;;)
`

bucket.ml:

`type 'a t = {
mutable arr: 'a array ;
mutable len: int ;
} ;;

(* We do not want this inlined.
*)
let [@inline never] grow s v =
let len0 = Array.length s.arr in
let len1 = len0 lsl 1 in
let arr1 = Array.make len1 v in
Array.blit s.arr 0 arr1 0 s.len ;
s.len <- len1 ;
s.arr <- arr1 ;
;;

(* We want this inlined.
*)
let [@inline] add s item =
if s.len >= Array.length s.arr then
grow s item ;
s.arr.(s.len) <- item ;
s.len <- succ s.len
;;`

noinline.zip

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions