Skip to content

Use "unboxable" as the name of the best-effort unboxing attribute #2319

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

Merged
merged 2 commits into from
Feb 28, 2024
Merged
Show file tree
Hide file tree
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
16 changes: 10 additions & 6 deletions middle_end/flambda2/docs/unboxed_params.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,14 @@ this only applies when the type/layout of the unboxed value is one of the follow
- boxed numbers (Float, Int32, Int64, Nativeint, Vec128)
- records/pairs[1]

Unboxing of variants will follow in the near future.

This unboxing is best-effort: in particular, indirect calls to functions
using this new optimization will still cause boxing.

## How does one unbox a parameter/return value ?

The `[@unboxed]` annotations are used to specify what to unbox in this context.
The `[@unboxable]` annotations are used to specify what to unbox in this context.
These annotations can be put either on a function parameter, or on a function declaration
to unbox its return value.

Expand All @@ -25,15 +29,15 @@ Here are some examples:
let f_boxed x y = x +. y

(* The same function, but this time with the return value unboxed *)
let[@unboxed] f_return x y = x +. y
let[@unboxable] f_return x y = x +. y

(* Again, `f`, but with only the first argument unboxed.
Note the parentheses around `x`, so that the annotation attaches to the parameter *)
let f_first (x[@unboxed]) y = x +. y
let f_first (x[@unboxable]) y = x +. y

(* Let's define a version of `f` with the first parameter unboxed, and the return
value unboxed, and mark it as never inline. *)
let[@unboxed] f (x[@unboxed]) y = x +. y [@@inline never]
let[@unboxable] f (x[@unboxable]) y = x +. y [@@inline never]

(* Using the definition of `f` just above, this `main` function does not allocate,
even with `f` not being inlined. *)
Expand All @@ -45,7 +49,7 @@ let main t y =

## What exactly happens ? What does it mean to unbox a parameter/return ?

Contrary to layouts/kinds/jkinds, the `[@unboxed]` annotation does not really change
Contrary to layouts/kinds/jkinds, the `[@unboxable]` annotation does not really change
the calling convention of functions. However, these annotations alter the compilation
strategy just enough so that the annotated function actually becomes a thin wrapper
around the unboxed version of the function. Later, that wrapper can be inlined (without
Expand All @@ -58,7 +62,7 @@ code will look like:
(* ***** Source code ***** *)

(* here are the original `f` and `main` functions *)
let[@unboxed] f (x[@unboxed]) y = x +. y [@@inline never]
let[@unboxable] f (x[@unboxable]) y = x +. y [@@inline never]

let main t y =
let x = t +. 1. in
Expand Down
4 changes: 2 additions & 2 deletions ocaml/lambda/printlambda.ml
Original file line number Diff line number Diff line change
Expand Up @@ -944,7 +944,7 @@ let rec lam ppf = function
let { unbox_param } = p.attributes in
fprintf ppf "@ %a%s%a%s"
Ident.print p.name (alloc_kind p.mode) layout p.layout
(if unbox_param then "[@unboxed]" else "")
(if unbox_param then "[@unboxable]" else "")
) params
| Tupled ->
fprintf ppf " (";
Expand All @@ -956,7 +956,7 @@ let rec lam ppf = function
Ident.print ppf p.name;
Format.fprintf ppf "%s" (alloc_kind p.mode);
layout ppf p.layout;
if unbox_param then Format.fprintf ppf "[@unboxed]"
if unbox_param then Format.fprintf ppf "[@unboxable]"
)
params;
fprintf ppf ")" in
Expand Down
18 changes: 9 additions & 9 deletions ocaml/lambda/translattribute.ml
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ let is_loop_attribute =
let is_opaque_attribute =
[ ["opaque"; "ocaml.opaque"], true ]

let is_unboxed_attribute =
[ ["unboxed"; "ocaml.unboxed"], true ]
let is_unboxable_attribute =
[ ["unboxable"; "ocaml.unboxable"], true ]

let find_attribute ?mark_used p attributes =
let inline_attribute =
Expand Down Expand Up @@ -591,13 +591,13 @@ let add_opaque_attribute expr loc attributes =
let add_unbox_return_attribute expr loc attributes =
match expr with
| Lfunction funct ->
let attr = find_attribute is_unboxed_attribute attributes in
let attr = find_attribute is_unboxable_attribute attributes in
begin match attr with
| None -> expr
| Some _ ->
if funct.attr.unbox_return then
Location.prerr_warning loc
(Warnings.Duplicated_attribute "unboxed");
(Warnings.Duplicated_attribute "unboxable");
let attr = { funct.attr with unbox_return = true } in
lfunction_with_attr ~attr funct
end
Expand Down Expand Up @@ -676,8 +676,8 @@ let add_function_attributes lam loc attr =
lam

let transl_param_attributes pat =
let attrs = pat.pat_attributes in
let unbox_param =
Option.is_some (find_attribute is_unboxed_attribute attrs)
in
{ unbox_param }
let attrs = pat.pat_attributes in
let unbox_param =
Option.is_some (find_attribute is_unboxable_attribute attrs)
in
{ unbox_param }