Skip to content

Conversation

bjorng
Copy link
Contributor

@bjorng bjorng commented Aug 28, 2025

The set_tuple_element instruction was used before OTP 26 to optimize chains of setelement/3 calls. For example:

foo(S0) when tuple_size(S0) =:= 8 ->
    S1 = setelement(8, S0, a),
    S2 = setelement(7, S1, b),
    setelement(5, S2, c).

The compiler would keep the first call to setelement/3 and replace the other two with set_tuple_element, which would destructively update the tuple created by the setelement/3 call.

Starting in OTP 26, this was changed so that all three setelement/3 calls are replaced with a single update_record instruction.

The set_tuple_element instruction was only used when the size of the tuple being updated was not known at compile time, as in the following example:

bar(S0) ->
    S1 = setelement(8, S0, a),
    S2 = setelement(7, S1, b),
    setelement(5, S2, c).

The only difference compared to the previous example is that the type of S0 is not known. When the size of the tuple cannot be determined at compile time, the compiler cannot use update_record and must fall back to setelement/3 and set_tuple_element. However, the way this fallback was implemented caused extra useless instructions to be generated (see #10125 for examples).

This commit eliminates the use of set_tuple_element in the fallback path, allowing us to remove some particularly messy code from beam_validator.

Resolves #10125

@bjorng bjorng requested review from jhogberg and lucioleKi August 28, 2025 12:33
@bjorng bjorng self-assigned this Aug 28, 2025
@bjorng bjorng added team:VM Assigned to OTP team VM testing currently being tested, tag is used by OTP internal CI labels Aug 28, 2025
Copy link
Contributor

github-actions bot commented Aug 28, 2025

CT Test Results

    4 files    457 suites   54m 23s ⏱️
2 327 tests 2 270 ✅ 57 💤 0 ❌
7 770 runs  7 694 ✅ 76 💤 0 ❌

Results for commit a144913.

♻️ 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

@bjorng bjorng added this to the OTP-29.0 milestone Aug 28, 2025
@michalmuskala
Copy link
Contributor

Do the sequences of setelement can take advantage of the mutability optimisation?

@bjorng
Copy link
Contributor Author

bjorng commented Aug 28, 2025

Do the sequences of setelement can take advantage of the mutability optimisation?

No. Optimization of setelement is only done when the size of the tuple is known at compile time. My pull request only handles tuples whose size are not known. When the size is not known, every setelement call is kept, but before this pull request additional useless set_tuple_element instructions were added. My pull request suppresses those extra instructions to reduce the code size.

@@ -1102,6 +1102,11 @@ void BeamModuleAssembler::emit_update_record_in_place(
void BeamModuleAssembler::emit_set_tuple_element(const ArgSource &Element,
const ArgRegister &Tuple,
const ArgWord &Offset) {
/* TODO: As of Erlang/OTP 29, this instruction is no longer
* emitted by the compiler. It can be removed when the runtime
* system no longer supports loading code compiled by Erlang/OTP
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for this!

lucioleKi
lucioleKi previously approved these changes Sep 1, 2025
jhogberg
jhogberg previously approved these changes Sep 2, 2025
@@ -204,8 +204,6 @@ validate_0([{function, Name, Arity, Entry, Code} | Fs], Module, Level, Ft) ->
hf=0,
%% List of hot catch/try tags
ct=[],
%% Previous instruction was setelement/3.
setelem=false,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can do a drive-by removal of puts_left too, it's not used anywhere.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea. Done.

The `set_tuple_element` instruction was used before OTP 26 to optimize chains of
`setelement/3` calls. For example:

    foo(S0) when tuple_size(S0) =:= 8 ->
        S1 = setelement(8, S0, a),
        S2 = setelement(7, S1, b),
        setelement(5, S2, c).

The compiler would keep the first call to `setelement/3` and replace
the other two with `set_tuple_element`, which would destructively
update the tuple created by the `setelement/3` call.

Starting in OTP 26, this was changed so that all three `setelement/3`
calls are replaced with a single `update_record` instruction.

The `set_tuple_element` instruction was only used when the size of the
tuple being updated was not known at compile time, as in the following
example:

    bar(S0) ->
        S1 = setelement(8, S0, a),
        S2 = setelement(7, S1, b),
        setelement(5, S2, c).

The only difference compared to the previous example is that the type
of `S0` is not known. When the size of the tuple cannot be determined
at compile time, the compiler cannot use `update_record` and must fall
back to `setelement/3` and `set_tuple_element`. However, the way this
fallback was implemented caused extra useless instructions to be
generated (see erlang#10125 for examples).

This commit eliminates the use of `set_tuple_element` in the fallback
path, allowing us to remove some particularly messy code from
`beam_validator`.

Resolves erlang#10125
@bjorng bjorng dismissed stale reviews from jhogberg and lucioleKi via a144913 September 3, 2025 05:12
@bjorng bjorng force-pushed the bjorn/compiler/eliminate-set_tuple_element/GH-10125/OTP-19751 branch from 596432e to a144913 Compare September 3, 2025 05:12
@bjorng bjorng requested review from lucioleKi and jhogberg September 3, 2025 05:13
@bjorng bjorng merged commit ae1ce45 into erlang:master Sep 3, 2025
28 of 30 checks passed
@bjorng bjorng deleted the bjorn/compiler/eliminate-set_tuple_element/GH-10125/OTP-19751 branch September 3, 2025 08:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
team:VM Assigned to OTP team VM testing currently being tested, tag is used by OTP internal CI
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Useless emission of a set_tuple_element opcode
5 participants