c++windowsvisual-c++memory-management

Does "automatic storage" now include registers?


In storage duration, I read that register storage has been deprecated for a long time (since C++98) and has been removed with C++17.

Yet, the compiler can still put variables into a register. I assume it will do this as part of automatic storage duration:

Automatic storage duration

The following variables have automatic storage duration :

Variables that belong to a block scope and are not explicitly declared static, thread_local,(since C++11) or extern. The storage for such variables lasts until the block in which they are created exits. Variables that belong to a parameter scope (i.e. function parameters). The storage for a function parameter lasts until immediately after its destruction.

To me, it looks like this description is satisfied for both, variables on the stack and variables in registers, given a Windows Desktop application and MSVC. Is this correct?

I just want to use the correct term when I talk to my colleagues, and I'm explicitly looking for something which can mean "stack or register".


Solution

  • register storage has been deprecated for a long time ... Yet, the compiler can still put variables into a register

    The register keyword has never been either required or particularly useful, on any C++ implementation I've worked with. At most it was a hint like inline was before it gained actual semantics.

    Does "automatic storage" now include registers?

    On the one hand: no, automatic storage tells us how long something lives, not where it lives. So long as the lifetime is correct, the standard has nothing to say about registers, or stacks, or other such implementation details.

    On the other hand: yes, automatic storage always included registers insofar as the compiler was always free to place automatic variables in registers if the abstract machine permitted. Nothing has changed in that respect.

    To me, it looks like this description is satisfied for both, variables on the stack and variables in registers, given a Windows Desktop application and MSVC. Is this correct?

    It's more accurate to say that all automatic variables satisfy this description as a matter of definition, however they are implemented.

    Automatic variables that are optimized into a register must behave as-if the variable exists for the whole scope, even though the register may be reused if the change is not observable.

    Automatic variables allocated (as an implementation detail) in a stack frame are guaranteed to satisfy this description only if stack frames are always emitted, there is no inlining or LTO, etc. That is, although automatic lifetime is in some sense related to stack frame calling conventions, it isn't satisfied automatically, but by some deliberate work of the compiler.

    Automatic variables can also be optimized out of course, and non-automatic objects such as static constexpr values may only ever exist in registers (if they materialize at all).

    Finally coroutines can have variables with automatic scope which are stored neither in a register nor in a stack frame, but in an object allocated by the promise's operator new.


    There anyway are other factors that affect whether variables can be optimized into a register, non-exhaustively:

    1. whether they fit
    2. whether the optimizer actually finds enough unused registers
    3. whether their address is ever taken
    4. whether they're ever used or passed by reference

    With the exception of function parameters - on a specific compiler, using a given ABI and with no inlining or LTO - you can never be 100% sure whether a variable eligible for this optimization is actually in a register at any point. Except by inspecting the assembly, and that will still be brittle in the face of compiler upgrades, compiler option changes, and code changes.