Move LC ++ Tail fusion from v3_core to sys_core_fold - #10912
Move LC ++ Tail fusion from v3_core to sys_core_fold#10912michalmuskala wants to merge 1 commit into
Conversation
When `[E || Qs] ++ Tail` is written, the compiler fuses the `++` into
the list comprehension's base case, replacing `[]` with `Tail` to
avoid an O(n) append traversal. Previously this optimization lived in
v3_core and only worked when the LC and `++` appeared in the same
expression. It failed when an intermediate variable separated them:
Expanded = [Exp || Exp <- Exps],
Expanded ++ Tail
Move the optimization to sys_core_fold where it can handle both cases.
After v3_core's `force_safe` binds the letrec to a variable, both the
inline and variable forms produce the same Core Erlang pattern:
let V = letrec lc/1 = ... in apply lc/1(List)
in call erlang:'++'(V, Tail)
The new `opt_lc_append` in `opt_let_2` detects this pattern and
rewrites the LC function to accept an extra tail parameter, replacing
the `[]` base case with the tail argument and eliminating the `++`
call entirely.
CT Test Results 2 files 335 suites 9m 19s ⏱️ Results for commit 742ca64. ♻️ This comment has been updated with latest results. To speed up review, make sure that you have read Contributing to Erlang/OTP and that all checks pass. See the TESTING and DEVELOPMENT HowTo guides for details about how to run test locally. Artifacts
// Erlang/OTP Github Action Bot |
|
Thanks @michalmuskala - I've hit this before and had to make the frustrating trade-off of code-style vs. performance. |
|
Thanks for your pull request. We'll include it in OTP 30. |
|
The following code is no longer optimized (slightly simplified from per_dec_named_integer(NamedList0, Int) ->
NamedList = [{K,V} || {V,K} <- NamedList0] ++ [integer_default],
{map,Int,NamedList}.Hint: I ran |
When
[E || Qs] ++ Tailis written, the compiler fuses the++into the list comprehension's base case, replacing[]withTailto avoid an O(n) append traversal. Previously this optimization lived in v3_core and only worked when the LC and++appeared in the same expression. It failed when an intermediate variable separated them:Move the optimization to sys_core_fold where it can handle both cases. After v3_core's
force_safebinds the letrec to a variable, both the inline and variable forms produce the same Core Erlang pattern:The new
opt_lc_appendinopt_let_2detects this pattern and rewrites the LC function to accept an extra tail parameter, replacing the[]base case with the tail argument and eliminating the++call entirely.