3

Please note: I was originally going to title this question "When to use registers in C?", however it seems like someone already beat me to the punch. However, the way that question was asked when compared to the title is a bit misleading, and I believe this question is unique and not a dupe of it.

Whereas, that question really ought to have been titled "Are register variables really faster?", I actually want to know when one should be using registers. It's obvious to me that they are in fact faster, but obviously your CPU only has so many register on chip, and so you are limited by what you can store on them.

So I ask: How do I select which variables should be qualified with register? Variables that are used with a certain frequency? Variables of a particular size or type? Variables that are used in compute-bound problems? Something else?

I look at it like this: to every product owner or stakeholder, every single bug or feature is "top priority" and critical. But if you really analyse their needs, you will see that some features are in deed more "top priority" than others. With code, you want it to run as fast as possible, and so I'm sure every variable is a candidate for optimization/performance tuning. But I would imagine that if you really analyse a program (or the C compiler for that matter, let's assume gcc), I'm sure there's a way to determine which variables are best suited for use with register.

Community
  • 1
  • 1
smeeb
  • 27,777
  • 57
  • 250
  • 447
  • 2
    I have pretty much removed `register` from all my code and I have no plans to reintroduce it anywhere (and anywhere it still exists simply hasn't been changed in the last decade or so). On the platforms I am interested in, the compiler will ignore what I say about registers and that's OK with me. It knows better than I do how to assign the registers. – Jonathan Leffler Jul 10 '15 at 07:57

4 Answers4

6

First, let me tell you, don't be fooled by the presence of register in your C source code.

Your compiler is absolutely free to ignore it (and most of time, it does). In modern compiler, using register is most probably useless.

Usually, any "standard" compiler will have their own algorithm to detect and put the appropriate variables to allocate them to registers (or not). Most of the time, they are surprisingly correct. Leave it to them.

FWIW, Only one thing to remember, you cannot get the address of a register variable. That is the only reason (if we can consider that as a "reason") to use register. maybe.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • Thanks @Sourav Ghosh (+1) - I completely understand your point about modern compilers *ignoring* `register`. But just so I understand 100% here: are you stating that *if* the compiler doesn't ignore it, then the only reason to use `register` would be for *security* purposes (variables with no addresses)? I guess I don't understand when/where it would be valuable for variables to not have addresses. Thoughts? Thanks again! – smeeb Jul 10 '15 at 07:27
  • @smeeb No, that was not my point. The last line is in regards with compiler _ignoring_ the `register`. It is better now? – Sourav Ghosh Jul 10 '15 at 07:29
  • 2
    There is no security related to this. Like the `auto` keyword, `register` is one as a part of the language and the behaviour of it is defined in the standards, therefore even if you use it, it will continue behaving as per the standards define it. – phoxis Jul 10 '15 at 07:31
  • @smeeb If at all, compiler can _afford_ to put **your** variable with `register` in the register instead of allocating it into stack, it will, no issue, but my point was, it's very very less likely and not at all guaranteed. Compiler can do (decide) that better, with or without the `register`. – Sourav Ghosh Jul 10 '15 at 07:31
0

There are times when register is useful ... when used with extended assembly.

#define STACK_POINTER "esp"
char **environ;
_start(void){
  register long *sp __asm__( STACK_POINTER );
  long argc = *sp;
  char **argv = (char **)(sp + 1);
  environ = (char **)(sp + argc + 1);
  exit(main(argc, argv, environ) );
  __builtin_unreachable(); //or for(;;); to shut up compiler about returning
}

In Linux (possibly others), elf binaries pass _start args on the stack even if the architecture passes some number of arguments as registers. Since there is no standardized way of accessing the stack pointer, you either have to write start in all assembly or use extensions like this to access a specific named register through a variable. You can also assign a value

register long *syscall_num __asm__( "eax" ) = __NR_open;
...

This is useful for the opposite situation where functions normally pass arguments on the stack, but a special function (syscall etc..) requires parameters to be passed in certain registers.

Theses two mechanisms will use registers if the compiler supports that syntax, but no, using register int i; or similar has no guarantees.

technosaurus
  • 7,676
  • 1
  • 30
  • 52
0

The register keyword is useful in defining extensions to calling ABIs, such as creating functions that can pass multiple parameters; or to globally allocate a register for local memory manager etc.

register int g_imag __asm__ ("r14");

int complex_multiply(int real, int imag, int r2, int i2)
{
    g_imag = real*i2 + imag*r2;    // put to "global" variable
    return real*r2 - imag*i2;
}

Only use callee saved registers to guarantee that functions using r14 to other purposes first spill the content to stack. The downside is the reduction of available registers in other functions, as well as others have pointed out, this only works when it works.

Aki Suihkonen
  • 19,144
  • 1
  • 36
  • 57
-1

As you know, register are fast access memory used by the CPU.They are mainly limited by their memory space, some are 8 bits, some are 256 bits. I remember it's around 10 times faster compared to DRAM, like 5 to 50 ns ( not sure ).

Using it depends on the field you are working on. For example, when working with embedded electronics it's usefull to use register , when you often use a global const, setting it as register will make your program " faster".

But keep in mind that's it's a matter of optimization,unless you are working with heavy demanding algorithms or embedded electronics, there is no need to dive into it. As it's said above, compilers can detect often used variables and try to store them in register,automatically.

But if you really want to use it, keep in mind that you should set variables or const that are very often used and aren't bigger than the register size !

borube
  • 59
  • 4
  • 2
    A good optimizing compiler will put in hardware registers variables which are not declared `register`, and will spill in RAM (stack frame) some variables declared `register`. So the `register` keyword is useless, except to forbid the address-of operator (`&x`). A compiler which needs `register` keyword annotation to put a value in a hardware register is a crappy compiler. – Basile Starynkevitch Jul 10 '15 at 07:38