File 0648-Efficiency-Guide-Update-the-setelement-3-section.patch of Package erlang
From fb9d861d958068056ede9d19cdb20d9f7b89c3dc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
Date: Tue, 26 Aug 2025 13:39:54 +0200
Subject: [PATCH] Efficiency Guide: Update the setelement/3 section
For multiple `setelement/3` calls to be coalesced, it is no longer
necessary to order the calls in order of descending indices.
---
system/doc/efficiency_guide/commoncaveats.md | 48 +++++++++++---------
1 file changed, 27 insertions(+), 21 deletions(-)
diff --git a/system/doc/efficiency_guide/commoncaveats.xmlsrc b/system/doc/efficiency_guide/commoncaveats.xmlsrc
index e46146ec9e..cc8f8db021 100644
@@ -180,8 +180,14 @@ foo([_,_,_|_]=L) ->
<p><seemfa marker="erts:erlang#setelement/3">setelement/3</seemfa>
copies the tuple it modifies. Therefore, updating a tuple in a loop
- using <c>setelement/3</c> creates a new copy of the tuple every time.</p>
+ using <c>setelement/3</c> creates a new copy of the tuple on each iteration.</p>
+ <title>Compiler optimizations of setelement/3</title>
+
+ <p>Under certain conditions, the compiler can coalesce multiple calls to
+ <c>setelement/3</c> into a single operation, avoiding
+ the cost of copying the tuple for each call.</p>
+ <p>For example:</p>
<p>There is one exception to the rule that the tuple is copied.
If the compiler clearly can see that destructively updating the tuple would
give the same result as if the tuple was copied, the call to
@@ -190,29 +196,27 @@ foo([_,_,_|_]=L) ->
call copies the tuple and modifies the ninth element:</p>
<code type="erl">
multiple_setelement(T0) ->
- T1 = setelement(9, T0, bar),
+ T1 = setelement(5, T0, new_value),
T2 = setelement(7, T1, foobar),
- setelement(5, T2, new_value).</code>
-
- <p>The two following <c>setelement/3</c> calls modify
- the tuple in place.</p>
+ setelement(9, T2, bar).</code>
- <p>For the optimization to be applied, <em>all</em> the following conditions
- must be true:</p>
+ <p>The compiler will replace the three <c>setelement/3</c> calls with code that
+ copies the tuple once and updates the elements at positions 5, 7, and 9.</p>
+ <p>Starting with Erlang/OTP 26, the following conditions must be met for
+ <c>setelement/3</c> calls to be coalesced into a single operation:</p>
<list type="bulleted">
- <item>The indices must be integer literals, not variables or expressions.</item>
- <item>The indices must be given in descending order.</item>
- <item>There must be no calls to another function in between the calls to
+ <item>The tuple argument must be known at compile time to be a tuple of a
+ specific size.</item>
+ <item>The element indices must be integer literals, not variables or expressions.</item>
+ <item>There must be no intervening expressions between the calls to
<c>setelement/3</c>.</item>
- <item>The tuple returned from one <c>setelement/3</c> call must only be used
- in the subsequent call to <c>setelement/3</c>.</item>
+ <item>The tuple returned from one <c>setelement/3</c> call must be
+ used only in the subsequent <c>setelement/3</c> call.</item>
</list>
- <p>If the code cannot be structured as in the <c>multiple_setelement/1</c>
- example, the best way to modify multiple elements in a large tuple is to
- convert the tuple to a list, modify the list, and convert it back to
- a tuple.</p>
+ <p>Before Erlang/OTP 26, an additional condition was that <c>setelement/3</c>
+ calls had to be made in descending order of indices.</p>
</section>
<section>
--
2.51.0