-
Notifications
You must be signed in to change notification settings - Fork 77
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
Flatten regions #1347
Flatten regions #1347
Conversation
f9bcebc
to
c1b79d7
Compare
c1b79d7
to
7691e17
Compare
This squashes 'flatten-regions' into a single commit over 'remove-regions-with-exclaves' and 'cmm-nested-exclaves' (PRs ocaml-flambda#1524 and ocaml-flambda#1529, respectively). Squashed commit of the following: commit bd23d8bd75478abafb67f0e791ef77bbd8764b22 Author: Luke Maurer <lmaurer@janestreet.com> Date: Fri Jun 30 16:03:06 2023 +0100 Clean up code commit 0ac81ecfc5b84eb286cbd5f0afc66d7f73b3eb92 Merge: c3a9203f9 9449e65 Author: Luke Maurer <lmaurer@janestreet.com> Date: Fri Jun 30 14:59:27 2023 +0100 Merge branch 'cmm-nested-exclaves' into flatten-regions commit c3a9203f9de900d8acbe77b781debbfb686a3d52 Merge: c1b79d7 d617694 Author: Luke Maurer <lmaurer@janestreet.com> Date: Fri Jun 30 14:57:23 2023 +0100 Merge branch 'remove-regions-with-exclaves' into flatten-regions commit c1b79d7 Author: Luke Maurer <lmaurer@janestreet.com> Date: Fri Jun 30 14:49:07 2023 +0100 Add example commit 033294f Author: Luke Maurer <lmaurer@janestreet.com> Date: Thu Jun 8 11:21:22 2023 +0100 Code review and provisional fixes These are fixes to issues that are really second- or third-order effects of region lifting and probably need their own PRs, but I'm committing them here for testing purposes. commit 65ad3aa Merge: e88df82 d65f752 Author: Luke Maurer <lmaurer@janestreet.com> Date: Thu May 25 17:00:33 2023 +0100 Merge remote-tracking branch 'upstream/main' into flatten-regions commit e88df82 Merge: de8cf43 9d3c1c1 Author: Luke Maurer <lmaurer@janestreet.com> Date: Thu May 11 13:21:45 2023 +0100 Merge remote-tracking branch 'upstream/main' into flatten-regions commit de8cf43 Author: Luke Maurer <lmaurer@janestreet.com> Date: Wed May 10 16:47:44 2023 +0100 Follow renaming of `Tail` to `Exclave` after merge commit ceae59a Merge: 8a717aa 63997c9 Author: Luke Maurer <lmaurer@janestreet.com> Date: Wed May 10 16:37:23 2023 +0100 Merge remote-tracking branch 'upstream/main' into flatten-regions commit 8a717aa Author: Luke Maurer <lmaurer@janestreet.com> Date: Wed May 10 16:26:33 2023 +0100 Don't try to be clever with `let x = M in tail x` There's nothing actually wrong with `let x = M in tail x`, so don't try to reduce it to just `M`. This works in that narrow case, but the code that was doing this transformation didn't notice if the body of the tail is more than just `x`. Since the transformation doesn't actually gain anything, better to be rid of it than to make things more complicated trying to get it right. Also updated a few comments and added an invariant check. commit 6fa1ce6 Author: Luke Maurer <lmaurer@janestreet.com> Date: Fri Apr 21 15:58:07 2023 +0100 Make `map_region_tail` look through regions as well commit d9043c9 Author: Luke Maurer <lmaurer@janestreet.com> Date: Fri Apr 21 14:14:19 2023 +0100 Check for close-on-apply on method calls as well as functions commit 58bf88a Author: Luke Maurer <lmaurer@janestreet.com> Date: Wed Apr 19 17:05:31 2023 +0100 Fix `Cmmgen` `Cmmgen` was (hopefully) the last remaining place where things were broken by the assumption that `region (region (tail (tail ...)))` never happens. commit 66132fb Author: Luke Maurer <lmaurer@janestreet.com> Date: Tue Apr 18 18:43:08 2023 +0100 Don't try to handle regions in `Flambda.fold_lets_option` It used to be much more necessary, but no more, and it interferes with the handling of regions using `enter_region`. commit 907627d Author: Luke Maurer <lmaurer@janestreet.com> Date: Tue Apr 18 18:41:18 2023 +0100 Refactor and clean up a bit commit dccb971 Author: Luke Maurer <lmaurer@janestreet.com> Date: Tue Apr 18 17:55:02 2023 +0100 Rewrite `let x = M in tail x` as `M` This should get rid of some annoying instances of extra variables introduced just to lift, and in particular stop making tail calls into non-tail calls. commit 6126e9e Merge: 5b62db1 e138734 Author: Luke Maurer <lmaurer@janestreet.com> Date: Wed Apr 12 14:31:25 2023 +0100 Merge remote-tracking branch 'upstream/main' into flatten-regions commit 5b62db1 Author: Luke Maurer <lmaurer@janestreet.com> Date: Wed Nov 30 17:37:40 2022 +0000 Lift regions along with `let`s This transforms expressions of the form ``` let x = region ( let y = E1 in E2 ) in E3 ``` into ``` region ( let y = E1 in let x = E2 in tail ( E3 ) ) ``` so that `y` is available when simplifying `E3` (as is the advantage of lifting `let`s to begin with). This requires that `E3` not already have a `tail` expression (or tail call) inside an `if` branch or any other construct besides the body of a `let`, `let mutable`, `region`, or `tail`.
7691e17
to
9b05a30
Compare
(** Lift lets in an expression. Note that [toplevel] here means either truly | ||
toplevel _or_ inside a toplevel function body. *) | ||
val lift_lets_expr | ||
: Flambda.t -> toplevel:bool -> in_closure:yes_no_or_maybe -> Flambda.t |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it might be cleaner if this was may_lift_regions:bool
instead of in_closure:yes_no_or_maybe
, since the No
and Maybe
cases aren't distinguished by this code and it's not obvious why being in a closure matters here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find it easier to keep track of simple syntactic properties like “Is it in a closure?” than “Are we allowed to lift a region here?”, especially when it comes to lines like this:
~f:(lift_lets_expr ~toplevel ~in_closure:Yes) set)) |
The answer to “Is it in a closure?” is clearly just “yes,” whereas the answer to “Are we allowed to lift a region here?” is contingent on flambda1's quirks. This way we get to express our policy about when to lift regions exactly once, in should_lift_regions
.
It was at one point a boolean, but I got tired of getting mixed up between “not known to be true” and “known not to be true” and decided to isolate that concern as well.
extract acc (W.of_expr body) | ||
extract acc dest (W.of_expr body) ~in_closure | ||
|
||
(* C[let x = region M in x] *) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think the body of the let is constrained to be x
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, this isn't very clear: body
is the body of the region, not the body of the let
. So it's M
in the expression.
Would these comments be any clearer if they read
<acc>[let <dest> = region <body> in <dest>]
and such? I find it helpful to be able to map a notional equational theory onto the implementation code, but clearly I went too far and tried to write a POPL paper in the comments ...
will move arbitrary computations - if there is a [Region] but no | ||
[Exclave], this means we're moving those computations into a different | ||
region. It may be that [acc_expr] already has an [Exclave] (because we | ||
lifted it out of [body]), but otherwise we need to add it. *) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is a single Exclave
definitely enough to fix this? Could there be two Region
s?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's only one Region
we need to worry about, and that's the one we're adding (on line 242). The extreme thing that acc_expr
could do is close more regions (that is, have more Exclave
s), which will be handled by outer calls to extract_region
.
We don't presently need this now we are all on flambda2, but if locals ends up upstream before flambda2, it would probably be needed. |
It's very important to take
and rewrite it to
so that, for instance, when simplifying
G
we're free to make use ofy
. This can be crucial for eliminating allocations:Here we can't easily eliminate the pair because we don't have a binding for the result of the projection. If we lift first, however:
This trivially reduces to
let y = E in y
(and further toE
, as it happens).Unfortunately, regions introduced by inlined calls get in the way of lifting:
In this case, currently we give up and don't allow
y
to be visible toG
at all. It is tempting to write:Unfortunately, this moves
G
into the region, which is an invalid transformation. However, we can fix this with an exclave:This patch enhances the
let
-floating transform in flambda1 by lifting most regions out in this way. This works whenever there isn't already an exclave (unless the exclave is particularly convenient - in particular, not buried in anif
orfor
or what-have-you) and will hopefully eliminate some heap allocations that have cropped up when turning on local allocations.