Stream: t-compiler/help

Topic: Referencing Locals allocated in registers


Lukas Diekmann (Jul 23 2020 at 14:13, on Zulip):

Hi, I'm trying to figure out what Rust does when we create a reference to a Local that was allocated in a register. In order to test this I looked at the machine code of some simple programs, but realised that Rust seems to always store Locals on the stack (only moving them into registers temporarily for further computation). For example, compiling let a = 1; I assumed that a would be allocated in a register, but it;s actually allocated on the stack. Wouldn't that be very slow? Maybe I'm just not compiling the right program. I feel like I am missing something here.

Jonas Schievink (Jul 23 2020 at 14:13, on Zulip):

Enable optimizations, then registers should be used whenever possible

Jonas Schievink (Jul 23 2020 at 14:14, on Zulip):

Of course, when you take a reference, the variable has to reside on the stack regardless

Lukas Diekmann (Jul 23 2020 at 14:15, on Zulip):

I compiled with --release with the same result.

simulacrum (Jul 23 2020 at 14:15, on Zulip):

Well, if the address is actually necessary, for example something like calling PartialEq::eq which takes references on two ints is unlikely to push things onto the stack in release mode.

simulacrum (Jul 23 2020 at 14:15, on Zulip):

Do you have the assembly in question?

simulacrum (Jul 23 2020 at 14:15, on Zulip):

(and program?)

Lukas Diekmann (Jul 23 2020 at 14:16, on Zulip):

Yes, I assume that once I create a reference, the Local is moved to the stack. I assume as long as the reference is alive, I can not move the Local back in to a register?

simulacrum (Jul 23 2020 at 14:17, on Zulip):

Rust doesn't give you direct knowledge of whether something is on the stack or the register in your program, and the optimization passes are free to do whatever (depending on the types and such in question).

Lukas Diekmann (Jul 23 2020 at 14:17, on Zulip):

The program is (no references in this example as I was trying to get Rust to use a register first)

fn main() {
    let mut a = 0;
    a = 3;
    println!("{}", a);
}
Jonas Schievink (Jul 23 2020 at 14:18, on Zulip):

println takes a reference

simulacrum (Jul 23 2020 at 14:18, on Zulip):

and the formatting infra is specifically tailored to not get inlined etc, optimizing for code size rather than speed for the most part

Lukas Diekmann (Jul 23 2020 at 14:19, on Zulip):

Ah, so because I'm printing a the compiler knows it needs to reference it, so it never gets allocated in a register in the first place.

Lukas Diekmann (Jul 23 2020 at 14:22, on Zulip):

Okay, this maybe more of a LLVM question then, but let's say a gets allocated in a register. I then reference a somewhere, which means it needs to be moved to the stack. How does the compiler know when it can move a back into a register. I assume once all references to a are dead?

Last update: Sep 28 2020 at 15:45UTC