From 20ffe7ca76c7ab442afbc176bed7d21f5bb5d7b8 Mon Sep 17 00:00:00 2001 From: Gergely Risko Date: Fri, 17 May 2024 15:02:17 +0200 Subject: [PATCH] Fix the debug exercise in the "Borrowing a Value" section 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. --- 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 68a8aa541308..268030ad156d 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).