How to store a C++ variable in a register - c++

I would like some clarification regarding a point about the storage of register variables:
Is there a way to ensure that if we have declared a register variable in our code, that it will ONLY be stored in a register?
#include<iostream>
using namespace std;
int main()
{
register int i = 10;// how can we ensure this will store in register only.
i++;
cout << i << endl;
return 0;
}

You can't. It is only a hint to the compiler that suggests that the variable is heavily used. Here's the C99 wording:
A declaration of an identifier for an object with storage-class specifier register suggests that access to the object be as fast as possible. The extent to which such suggestions are effective is implementation-defined.
And here's the C++11 wording:
A register specifier is a hint to the implementation that the variable so declared will be heavily used. [ Note: The hint can be ignored and in most implementations it will be ignored if the address of the variable is taken. This use is deprecated (see D.2). —end note ]
In fact, the register storage class specifier is deprecated in C++11 (Annex D.2):
The use of the register keyword as a storage-class-specifier (7.1.1) is deprecated.
Note that you cannot take the address of a register variable in C because registers do not have an address. This restriction is removed in C++ and taking the address is pretty much guaranteed to ensure the variable won't end up in a register.
Many modern compilers simply ignore the register keyword in C++ (unless it is used in an invalid way, of course). They are simply much better at optimizing than they were when the register keyword was useful. I'd expect compilers for niche target platforms to treat it more seriously.

The register keyword has different meanings in C and C++. In C++ it is in fact redundant and seems even to be deprecated nowadays.
In C it is different. First don't take the name of the keyword literally, it is has not always to do with a "hardware register" on a modern CPU. The restriction that is imposed on register variables is that you can't take their address, the & operation is not allowed. This allows you to mark a variable for optimization and ensure that the compiler will shout at you if you try to take its address. In particular a register variable that is also const qualified can never alias, so it is a good candidate for optimization.
Using register as in C systematically forces you to think of every place where you take the address of a variable. This is probably nothing you would want to do in C++, which heavily relies on references to objects and things like that. This might be a reason why C++ didn't copy this property of register variables from C.

Generally it's impossibly. Specifically one can take certain measures to increase the probability:
Use proper optimization level eg. -O2
Keep the number of the variables small
register int a,b,c,d,e,f,g,h,i, ... z; // can also produce an error
// results in _spilling_ a register to stack
// as the CPU runs out of physical registers
Do not take an address of the register variable.
register int a;
int *b = &a; /* this would be an error in most compilers, but
especially in the embedded world the compilers
release the restrictions */
In some compilers, you can suggest
register int a asm ("eax"); // to put a variable to a specific register

Generally CPP compilers(g++) do quite a few optimizations to the code. So when you declare a register variable, it is not necessary that the compiler will store that value directly in the register. (i.e) the code 'register int x' may not result in compiler storing that int directly in the register. But if we can force the compiler to do so, we may be successful.
For example, if we use the following piece of code, then we may force the compiler to do what we desire. Compilation of the following piece of code may error out, which indicates that the int is actually getting stored directly in the register.
int main() {
volatile register int x asm ("eax");
int y = *(&x);
return 0;
}
For me, g++ compiler is throwing the following error in this case.
[nsidde#nsidde-lnx cpp]$ g++ register_vars.cpp
register_vars.cpp: In function ‘int main()’:
register_vars.cpp:3: error: address of explicit register variable ‘x’ requested
The line 'volatile register int x asm ("eax")' is instructing the compiler that, store the integer x in 'eax' register and in doing so do not do any optimizations. This will make sure that the value is stored in the register directly. That is why accessing the address of the variable is throwing an error.
Alternatively, the C compiler (gcc), may error out with the following code itself.
int main() {
register int a=10;
int c = *(&a);
return 0;
}
For me, the gcc compiler is throwing the following error in this case.
[nsidde#nsidde-lnx cpp]$ gcc register.c
register.c: In function ‘main’:
register.c:5: error: address of register variable ‘a’ requested

It's just a hint to the compiler; you can't force it to place the variable in a register. In any event, the compiler writer probably has much better knowledge of the target architecture than the application programmer, and is therefore better placed to write code that makes register allocation decisions. In other words, you are unlikely to achieve anything by using register.

The "register" keyword is a remnant of the time when compilers had to fit on machines with 2MB of RAM (shared between 18 terminals with a user logged in on each). Or PC/Home computers with 128-256KB of RAM. At that point, the compiler couldn't really run through a large function to figure out which register to use for which variable, to use the registers most effectively. So if the programmer gave a "hint" with register, the compiler would put that in a register (if possible).
Modern compilers don't fit several times in 2MB of RAM, but they are much more clever at assigning variables to registers. In the example given, I find it very unlikley that the compiler wouldn't put it in a register. Obviously, registers are limited in number, and given a sufficiently complex piece of code, some variables will not fit in registers. But for such a simple example, a modern compiler will make i a register, and it will probably not touch memory until somewhere inside ostream& ostream::operator<<(ostream& os, int x).

The only way to ensure that you are using a register, is to use inline assembly. But, even if you do this, you are not guaranteed that the compiler won't store your value outside of the inline assembly block. And, of course, your OS may decide to interrupt your program at any point, storing all your registers to memory, in order to give the CPU to another process.
So, unless you write assembler code within the kernel with all interrupts disabled, there is absolutely no way to ensure that your variable will never hit memory.
Of course, that is only relevant if you are concerned about safety. From a performance perspective, compiling with -O3 is usually enough, the compiler usually does quite a good job at determining which variables to hold in registers. Anyway, storing variables in registers is only one small aspect of performance tuning, the much more important aspect is to ensure that no superfluous or expensive work gets done in the inner loop.

Here you can use volatile register int i = 10 in C++ to ensure i to be stored in register. volatile keyword will not allow the compiler to optimize the variable i.

Related

Is it possible to make variable truly read-only in C++?

By using the const qualifier a variable is supposed to be made read-only. As an example, an int marked const cannot be assigned to:
const int number = 5; //fine to initialize
number = 3; //error, number is const
At first glance it looks like this makes it impossible to modify the contents of number. Unfortunately, actually it can be done. As an example const_cast could be used (*const_cast<int*>(&number) = 3). This is undefined behavior, but this doesn't guarantee that number does not actually get modified. It could cause the program to crash, but it could also simply modify the value and continue.
Is it possible to make it actualy impossible to modify a variable?
A possible need for this might be security concerns. It might need to be of highest importance that some very valuable data must not be changed or that a piece of data being sent must not be modified.
No, this is not the concern of a programming language. Any "access" protection is only superficial and only exists at compile-time.
Memory of a computer can always be modified at runtime if you have the corresponding rights. Your OS might provide you with facilities to secure pages of memory though, e.g VirtualProtect() under Windows.
(Notice that an "attacker" could use the same facilities to restore the access if he has the privilege to do so)
Also I assume that there might be hardware solutions for this.
There is also the option of encrypting the data in question. Yet it appears to be a chicken-and-egg situation as the private key for the encryption and decryption has to be stored somewhere in memory as well (with a software-only solution).
While most of the answers in this thread are correct, but they are related to const, while the OP is asking for a way to have a constant value defined and used in the source code. My crystal ball says that OP is looking for symbolic constants (preprocessor #define statements).
#define NUMBER 3
//... some other code
std::cout<<NUMBER;
This way, the developer is able to parametrize values and maintain them easily, while there's virtually no (easy) way to alter it once the program is compiled and launched.
Just keep in mind that const variables are visible to debuggers, while symbolic constants are not, but they require no additional memory. Another criteria is the type checking, which is absent in case of symbolic constants, as well as for macros.
const is not intended to make a variable read-only.
The meaning of const x is basically:
Hey compiler, please prevent me from casually writing code in this scope which changes x.
That's very different from:
Hey compiler, please prevent any changes to x in this scope.
Even if you don't write any const_cast's yourself - the compiler will still not assume that const'ed entities won't change. Specifically, if you use the function
int foo(const int* x);
the compiler cannot assume that foo() doesn't change the memory pointed to by x.
You could use your value without a variable
Variables vary... so, naturally, a way to prevent that is using values which aren't stored in variables. You can achieve that by using...
an enumeration with a single value: enum : int { number = 1 }.
the preprocessor: #define NUMBER 1 <- Not recommended
a function: inline int get_number() { return 1; }
You could use implementation/platform-specific features
As #SebastianHoffman suggests, typical platforms allow marking some of a process' virtual memory space as read-only, so that attempts to change it result in an access violation signal to the process and the suspension of its execution. This is not a solution within the language itself, but it is often useful. Example: When you use string literals, e.g.:
const char* my_str = "Hello world";
const_cast<char*>(my_str)[0] = 'Y';
Your process will likely fail, with a message such as:
Segmentation fault (core dumped)
If you know the program at compile-time, you can place the data in read-only memory. Sure, someone could get around this, but security is about layers rather than absolutes. This makes it harder. C++ has no concept of this, so you'll have to inspect the resulting binary to see if it's happened (this could be scripted as a post-build check).
If you don't have the value at compile-time, your program depends on being able to change / set it at runtime, so you fundamentally cannot stop that from happening.
Of course, you can make it harder though things like const so the code is compiled assuming it won't change / programmers have a harder time accidentally changing it.
You may also find constexpr an interesting tool to explore here.
There is no way to specify what code does that does not adhere to the specification.
In your example number is truly constant. You correctly note that modifiying it after a const_cast would be undefined beahvior. And indeed it is impossible to modify it in a correct program.

C++ Statement Reordering

This is a question about Chandler's answer here (I didn't have a high enough rep to comment): Enforcing statement order in C++
In his answer, suppose foo() has no input or output. It's a black box that does work that is observable eventually, but won't be needed immediately (e.g. executes some callback). So we don't have input/output data locally handy to tell the compiler not to optimize. But I know that foo() will modify the memory somewhere, and the result will be observable eventually. Will the following prevent statement reordering and get the correct timing in this case?
#include <chrono>
#include <iostream>
//I believe this tells the compiler that all memory everywhere will be clobbered?
//(from his cppcon talk: https://youtu.be/nXaxk27zwlk?t=2441)
__attribute__((always_inline)) inline void DoNotOptimize() {
asm volatile("" : : : "memory");
}
// The compiler has full knowledge of the implementation.
static int ugly_global = 1; //we print this to screen sometime later
static void foo(void) { ugly_global *= 2; }
auto time_foo() {
using Clock = std::chrono::high_resolution_clock;
auto t1 = Clock::now(); // Statement 1
DoNotOptimize();
foo(); // Statement 2
DoNotOptimize();
auto t2 = Clock::now(); // Statement 3
return t2 - t1;
}
Will the following prevent statement reordering and get the correct timing in this case?
It should not be necessary because the calls to Clock::now should, at the language-definition level, enforce enough ordering. (That is, the C++11 standard says that the high resolution clock ought to get as much information as the system can give here, in the way that is most useful here. See "secondary question" below.)
But there is a more general case. It's worth thinking about the question: How does whoever provides the C++ library implementation actually write this function? Or, take C++ itself out of the equation. Given a language standard, how does an implementor—a person or group writing an implementation of that language—get you what you need? Fundamentally, we need to make a distinction between what the language standard requires and how an implementation provider goes about implementing the requirements.
The language itself may be expressed in terms of an abstract machine, and the C and C++ languages are. This abstract machine is pretty loosely defined: it executes some kind of instructions, which access data, but in many cases we don't know how it does these things, or even how big the various data items are (with some exceptions for fixed-size integers like int64_t), and os on. The machine may or may not have "registers" that hold things in ways that cannot be addressed as well as memory that can be addressed and whose addresses can be recorded in pointers:
p = &var
makes the value store in p (in memory or a register) such that using *p accesses the value stored in var (in memory or a register—some machines, especially back in the olden days, have / had addressable registers).1
Nonetheless, despite all of this abstraction, we want to run real code on real machines. Real machines have real constraints: some instructions might require particular values in particular registers (think about all the bizarre stuff in the x86 instruction sets, or wide-result integer multipliers and dividers that use special-purpose registers, as on some MIPS processors), or cause CPU sychronizations, or whatever.
GCC in particular invented a system of constraints to express what you could or could not do on the machine itself, using the machine's instruction set. Over time, this evolved into user-accessible asm constructs with input, output, and clobber sections. The particular one you show:
__attribute__((always_inline)) inline void DoNotOptimize() {
asm volatile("" : : : "memory");
}
expresses the idea that "this instruction" (asm; the actual provided instruction is blank) "cannot be moved" (volatile) "and clobbers all of the computer's memory, but no registers" ("memory" as the clobber section).
This is not part of either C or C++ as a language. It's just a compiler construction, supported by GCC and now supported by clang as well. But it suffices to force the compiler to issue all stores-to-memory before the asm, and reload values from memory as needed after the asm, in case they changed when the computer executed the (nonexistent) instruction included in the asm line. There's no guarantee that this will work, or even compile at all, in some other compiler, but as long as we're the implementor, we choose the compiler we're implementing for/with.
C++ as a language now has support for ordered memory operations, which an implementor must implement. The implementor can use these asm volatile constructs to achieve the right result, provided they do actually achieve the right result. For instance, if we need to cause the machine itself to synchronize—to emit a memory barrier—we can stick the appropriate machine instruction, such as mfence or membar #sync or whatever it may be, in the asm's instruction-section clause. See also compiler reordering vs memory reordering as Klaus mentioned in a comment.
It is up to the implementor to find an appropriately effective trick, compiler-specific or not, to get the right semantics while minimizing any runtime slowdown: for instance, we might want to use lfence rather than mfence if that's sufficient, or membar #LoadLoad, or whatever the right thing is for the machine. If our implementation of Clock::now requires some sort of fancy inline asm, we write one. If not, we don't. We make sure that we produce what's required—and then all users of the system can just use it, without needing to know what sort of grubby implementation tricks we had to invoke.
There's a secondary question here: does the language specification really constrain the implementor the way we think/hope it does? Chris Dodd's comment says he thinks so, and he's usually right on these kinds of questions. A couple of other commenters think otherwise, but I'm with Chris Dodd on this one. I think it is not necessary. You can always compile to assembly, or disassemble the compiled program, to check, though!
If the compiler didn't do the right thing, that asm would force it to do the right thing, in GCC and clang. It probably wouldn't work in other compilers.
1On the KA-10 in particular, the registers were just the first sixteen words of memory. As the Wikipedia page notes, this meant you could put instructions into there and call them. Because the first 16 words were the registers, these instructions ran much faster than other instructions.

Does the inline asm compiler barrier (memory clobber) count as an external function, or as static function call?

Introduction/confirmation of basic facts
It is well known that with GCC style C and C++ compilers, you can use inline assembly with a "memory" clobber:
asm("":::"memory");
to prevent reordering of (most) code past it, acting as a (thread local) "memory barrier" (for example for the purpose of interacting with async signals).
Note: these "compiler barriers" do NOT accomplish inter-threads synchronization.
It does the equivalent of a call to a non inline function, potentially reading all objects that can be read outside of the current scope and altering all those that can be altered (non const objects):
int i;
void f() {
int j = i;
asm("":::"memory"); // can change i
j += i; // not j *= 2
// ... (assume j isn't unused)
}
Essentially it's the same as calling a NOP function that's separately compiled, except that the non inline NOP function call is later (1) inlined so nothing survives from it.
(1) say, after compiler middle pass, after analysis
So here j cannot be changed as it's local, and is still the copy of the old i value, but i might have changed, so the compilation is pretty much the same as:
volatile int vi;
int f2() {
int j = vi;
; // can "change" vi
j += vi; // not j *= 2
return j;
}
Both reads of vi are needed (for a different reason) so the compiler doesn't change that into 2*vi.
Is my understanding correct up to that point? (I presume it is. Otherwise the question doesn't make sense.)
The real issue: extern or static
The above was just the preamble. The issue I have is with static variables, possible calls to static functions (or the C++ equivalent, anonymous namespaces):
Can a memory clobber access static data that isn't otherwise accessible via non static functions, and call static functions that aren't otherwise callable, as none of these are visible at link stage, from other modules, if they aren't named explicitly in the input arguments of the asm directive?
static int si;
int f3() {
int j = si;
asm("":::"memory"); // can access si?
j += si; // optimized to j = si*2; ?
return j;
}
[Note: the use of static is a little ambiguous. The suggestion is that the boundary of the TU is important, and that the static variable is TU-private, but I have not described how it was manipulated. Let's assume it is really manipulated that in that TU, or the compiler might assume it's effectively a constant.]
In other words, is that "clobber" the equivalent of a call to:
an external NOP function, which wouldn't be able to name si directly, nor to access it in any indirect way, as no function in the TU either communicates the address of si, or makes si indirectly modifiable
a locally defined NOP function that can access si
?
Bonus question: global optimization
If the answer is that static variables aren't treated like extern variables in that case, what is the impact when compiling the program at once? More specifically:
During global compilation of the whole program, with global analysis and inference over variables values, is the knowledge of the fact that for example a global variable is never modified (or never assigned a negative value...), except possibly in an asm "clobber", an input of the optimizer?
In other words, if non static i is only named in one TU, can it be optimized as if it was a static int even if there are asm statements? Should global variables be explicitly listed as clobbers in that case?
It does the equivalent of a call to a non inline function, potentially reading all objects that can be read outside of the current scope and altering all those that can be altered (non const objects):
No.
The compiler can decide to inline any function in the same compilation unit (and then, if the function wasn't static, also provide a separate "not inlined" copy for callers in other compilation units so that the linker can find one); and with link-time code optimization/link-time code generation the linker can decide to inline any functions in different compilation units. The only case where it's currently impossible for any function to be inlined is when it is in a shared library; but this limitation currently exists because operating systems currently aren't capable of "load-time optimization".
In other words; any appearance of any kind of barrier for any function is an unintended side-effect of optimizer weaknesses and not guaranteed; and therefore can not/should not be relied on.
The real issue: inline assembly
There are 5 possibilities:
a) The compiler understands all assembly, and is able to examine the inline assembly and determine what is/isn't clobbered; there is no clobber list (and no need for one). In this case (depending on how advanced the compiler/optimiser is) the compiler may be able to determine things like "this area of memory may be clobbered but that area of memory won't be clobbered" and avoid the cost of reloading data from the area of memory that wasn't clobbered.
b) The compiler doesn't understand any assembly and there is no clobber list, so the compiler has to assume everything will be clobbered; which means that the compiler has to generate code that saves the everything (e.g. currently in use values in registers, etc) to memory before the inline assembly is executed and reload everything afterwards, which will give extremely bad performance.
c) The compiler doesn't understand any assembly, and expects the programmer to provide a clobber list to avoid (some of) the performance disaster of having to assume everything will be clobbered.
d) The compiler understands some assembly but not all assembly, and doesn't have a clobber list. If it doesn't understand the assembly it assumes everything may have been clobbered.
e) The compiler understands some assembly but not all assembly, and does have an (optional?) clobber list. If it doesn't understand the assembly it relies on the clobber list (and/or falls back to "assume everything is clobbered" if there is no clobber list), and if it does understand the assembly it ignores the clobber list.
Of course a compiler that uses "option c)" can be improved to use "option e)"; and a compiler that uses "option e)" can be improved to use "option a)".
In other words; any appearance of any kind of barrier for something like "asm("":::"memory");" is an unintended side-effect of the compiler being "improvable"; and therefore can not/should not be relied on.
Summary
None of the things you've mentioned are actually a barrier of any kind. It's all just "unintended and undesired failure to optimize".
If you do need a barrier, then use an actual barrier (e.g. "asm("mfence":::"memory");". However (unless you need inter-threads synchronization and aren't using atomics) its extremely likely that you do not need a barrier in the first place.

const vs #define in modern compilers

I've read a few things saying that a #define doesn't take up any memory, but a colleague at work was very insistent that modern compilers don't have any differences when it comes to const int/strings.
#define STD_VEC_HINT 6;
const int stdVecHint = 6;
The conversation came about because an old bit of code that was being modernised that dealt with encryption that had its key as a #define.
I always thought that a variable would end up getting a memory address which would show its contents, but maybe compiling under release removes such stuff.
A good compiler will not allocate space for a const variable that can be elided. In C++, const variables at the module scope are also implicity static in visibility, so it's easier for the compiler to optimize out the variable as well. The link time optimization feature of GCC helps as well to do cross-module optimization.
Don't forget the even more important fact that const variables have proper scoping and type safety, which are missing from #define.
As with so many thinks, it depends..!
A #define will just inject the constant straight into your code, so it won't take up any memory. The same is potentially true for a const.
However, you can take the address of a const:
const int *value = &stdVecHint;
And since you're taking its address the compiler will need to store the constant in memory in order to generate an address, so in this case it will require memory.
The compiler is likely to replace occurrences with stdVecHint with the literal 6 everywhere it is used. An address and memory space will be taken up if you take its address explicitly, but then again this is a moot point since you couldn't do that with the STD_VEC_HINT. Pedantically, yes, stdVecHint is a variable with internal linkage and every translation unit that sees the definition will have its own copy of it. In practice, it shouldn't increase the memory footprint.
Pre-processor command uses this type of command like #define ,....
and no need to allocate memory because
and change name of constant [#define pi 3.14] like pi with 3.14 and then compile code
but in const command [const float pi=3.14;] need to memory allocation
For compatibility with older versions of the preprocessor is no problem, but future unclear
be successfull

Is the register keyword still used?

Just came across the register keyword in C++ and I wondered as this seems a good idea (keeping certain variables in a register) surely the compiler does this by default?
So I wondered is this keyword still used?
Most implementations just ignore the register keyword (unless it imposes a syntactical or semantical error).
The standard also doesn't say that anything must be kept in a register; merely that it's a hint to the implementation that the variable is going to be used very often. Its use is even deprecated.
7.1.1 Storage class specifiers [dcl.stc]
3) A register specifier is a hint to the implementation that the variable so declared will be heavily used. [ Note: The hint can be ignored and in most implementations it will be ignored if the address of the variable is taken. This use is deprecated (see D.2). — end note ]
The standard says this (7.1.1(2-3)):
The register specifier shall be applied only to names of variables declared in a block (6.3) or to function parameters (8.4). It specifies that the named variable has automatic storage duration (3.7.3). A variable declared without a storage-class-specifier at block scope or declared as a function parameter has automatic storage duration by default.
A register specifier is a hint to the implementation that the variable so declared will be heavily used. [ Note: The hint can be ignored and in most implementations it will be ignored if the address of the variable is taken. This use is deprecated (see D.2). — end note ]
In summary: register is useless, vestigial, atavistic and deprecated. Its main purpose is to make the life of people harder who are trying to implement self-registering classes and want to name the main function register(T *).
Probably the only remotely serious use for the register keyword left is a GCC extension that allows you to use a hard-coded hardware register without inline assembly:
register int* foo asm("a5");
This will mean that any access to foo will affect the CPU register a5.
This extension of course has little use outside of very low-level code.
Only specific number of registers are available for any C++ program.
Also, it is just a suggestion for the compiler mostly compilers can do this optimization themselves so there is not really much use of using register keyword and so more because compilers may or may not follow the suggestion.
So the only thing register keyword does with modern compilers is prevent you from using & to take the address of the variable.
Using the register keyword just prevents you from taking the address of the variable in C, while in C++ taking the address of the variable just makes the compiler ignore the register keyword.
Bottomline is, Just don't use it!
Nicely explained by Herb:
Keywords That Aren't (or, Comments by Another Name)
No, it's not used. It's only a hint, and a very weak one at that. Compilers have register allocators, they can figure out which variables should be kept in registers (and account for things you probably never thought about).
The keyword "register" has been deprecated since the 2011 C++ standard; see "Remove Deprecated Use of the register Keyword". It should therefore not be used.
In my own experiments I found that debug code generated by gcc (v8.1.1) does differ if the "register" keyword is used; the generated assembly code allocates designated variables to registers. Benchmarks even showed that this code ran faster (than code without "register"). This is irrelevant, however, as release (optimised) code showed no differences (ie, using "register" had no effect). Vacbob states here that if any optimization is enabled, then gcc ignores "register". My own tests confirm this.
So, in summary, don't use "register" and if debug code appears to run faster when "register" is used, bear in mind that the optimized release code will not.