From 889a4cbbeebec9707269d3b25446a2e0828c0c9d Mon Sep 17 00:00:00 2001 From: Gergely Risko Date: Fri, 17 May 2024 16:07:47 +0200 Subject: [PATCH] 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. --- src/borrowing/shared.md | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/borrowing/shared.md b/src/borrowing/shared.md index 68a8aa54..268030ad 100644 --- a/src/borrowing/shared.md +++ b/src/borrowing/shared.md @@ -35,14 +35,14 @@ slightly to include function arguments and return values. # More to Explore -Notes on stack returns: +Notes on stack returns and inlining: - Demonstrate that the return from `add` is cheap because the compiler can - eliminate the copy operation. Change the above code to print stack addresses - and run it on the [Playground] or look at the assembly in - [Godbolt](https://rust.godbolt.org/). In the "DEBUG" optimization level, the - addresses should change, while they stay the same when changing to the - "RELEASE" setting: + eliminate the copy operation, by inlining the call to add into main. Change + the above code to print stack addresses and run it on the [Playground] or look + at the assembly in [Godbolt](https://rust.godbolt.org/). In the "DEBUG" + optimization level, the addresses should change, while they stay the same when + changing to the "RELEASE" setting: ```rust,editable @@ -63,11 +63,12 @@ Notes on stack returns: println!("{p1:?} + {p2:?} = {p3:?}"); } ``` -- The Rust compiler can do return value optimization (RVO). -- In C++, copy elision has to be defined in the language specification because - constructors can have side effects. In Rust, this is not an issue at all. If - RVO did not happen, Rust will always perform a simple and efficient `memcpy` - copy. +- The Rust compiler can do automatic inlining, that can be disabled on a + function level with `#[inline(never)]`. +- Once disabled, the printed address will change on all optimization levels. + Looking at Godbolt or Playground, one can see that in this case, the return of + the value depends on the ABI, e.g. on amd64 the two i32 that is making up the + point will be returned in 2 registers (eax and edx).