Skip to content

Commit 889a4cb

Browse files
authored
Fix the debug exercise in the "Borrowing a Value" section (#2083)
Trying to reproduce this RVO shows that actually the optimization that is used here is simple inlining. Once inlining is disabled, the addresses change, even with `-O -C opt-level=3`. The return of the values is also never changed to an "efficient memcpy", but instead was returned on eax+edx, although this result is of course specific to the calling convention of the platform ABI, but no memcpy on the most popular amd64 architecture. I don't think it's educationally important to teach RVO here, so I didn't go into any length trying to force Rust to do a real RVO (passing Point address into the function on the assembly level, so the function can fill in the addition). In my opinion the only important thing is, that if a student is actually clicking the Playground link and looks into the assembly, then our description should match the generated code. That's why I just fixed the content instead of trying to fix the example to be RVO.
1 parent cf057e1 commit 889a4cb

File tree

1 file changed

+12
-11
lines changed

1 file changed

+12
-11
lines changed

src/borrowing/shared.md

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,14 @@ slightly to include function arguments and return values.
3535

3636
# More to Explore
3737

38-
Notes on stack returns:
38+
Notes on stack returns and inlining:
3939

4040
- Demonstrate that the return from `add` is cheap because the compiler can
41-
eliminate the copy operation. Change the above code to print stack addresses
42-
and run it on the [Playground] or look at the assembly in
43-
[Godbolt](https://rust.godbolt.org/). In the "DEBUG" optimization level, the
44-
addresses should change, while they stay the same when changing to the
45-
"RELEASE" setting:
41+
eliminate the copy operation, by inlining the call to add into main. Change
42+
the above code to print stack addresses and run it on the [Playground] or look
43+
at the assembly in [Godbolt](https://rust.godbolt.org/). In the "DEBUG"
44+
optimization level, the addresses should change, while they stay the same when
45+
changing to the "RELEASE" setting:
4646

4747
<!-- mdbook-xgettext: skip -->
4848
```rust,editable
@@ -63,11 +63,12 @@ Notes on stack returns:
6363
println!("{p1:?} + {p2:?} = {p3:?}");
6464
}
6565
```
66-
- The Rust compiler can do return value optimization (RVO).
67-
- In C++, copy elision has to be defined in the language specification because
68-
constructors can have side effects. In Rust, this is not an issue at all. If
69-
RVO did not happen, Rust will always perform a simple and efficient `memcpy`
70-
copy.
66+
- The Rust compiler can do automatic inlining, that can be disabled on a
67+
function level with `#[inline(never)]`.
68+
- Once disabled, the printed address will change on all optimization levels.
69+
Looking at Godbolt or Playground, one can see that in this case, the return of
70+
the value depends on the ABI, e.g. on amd64 the two i32 that is making up the
71+
point will be returned in 2 registers (eax and edx).
7172

7273
</details>
7374

0 commit comments

Comments
 (0)