Is it useless to use the `register` keyword with modern compilers, when optimizing?

﹥>﹥吖頭↗ 提交于 2020-04-06 21:50:12

问题


The C register keyword gives the compiler a hint to prefer storing a variable in a register rather than, say, on the stack. A compiler may ignore it if it likes. I understand that it's mostly-useless these days when you compile with optimization turned on, but is it entirely useless?

More specifically: For any combination of { gcc, clang, msvc } x { -Og, -O, -O2, -O3 }: Is register ignored when deciding whether to actually assign a register? And if not, are there cases in which it's useful enough to bother using it?

Notes:

  • I am not asking whether it the keyword any effect; of course it does - it prevents you from using the address of that variable; and if you don't optimize at all, it will make the difference between register assignment or memory assignment for your variable.
  • Answers for just one compiler / some of the above combinations are very welcome.

回答1:


For GCC, register has had no effect on code generation at all, not even a hint, at all optimization levels, for all supported CPU architectures, for over a decade.

The reasons for this are largely historical. GCC 2.95 and older had two register allocators, one ("stupid") used when not optimizing, and one ("local, global, reload") used when optimizing. The "stupid" allocator did try to honor register, but the "local, global, reload" allocator completely ignored it. (I don't know what the original rationale for that design decision was; you'd have to ask Richard Kenner.) In version 3.0, the "stupid" allocator was scrapped in favor of adding a fast-and-sloppy mode to "local, global, reload". Nobody bothered to write the code to make that mode pay attention to register, so it doesn't.

As of this writing, the GCC devs are in the process of replacing "local, global, reload" with a new allocator called "IRA and LRA", but it, too, completely ignores register.

However, the (C-only) rule that you cannot take the address of a register variable is still enforced, and the keyword is used by the explicit register variable extension, which allows you to dedicate a specific register to a variable; this can be useful in programs that use a lot of inline assembly.




回答2:


C Standard says:

(c11, 6.7.1p6) "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."

These suggestions being implementation-defined means the implementation must define the choices being made ((c11, J.3.8 Hints) "The extent to which suggestions made by using the register storage-class specifier are effective (6.7.1)").

Here is what the documentation of some popular C compilers says.

For gcc (source):

The register specifier affects code generation only in these ways:

  • When used as part of the register variable extension, see Explicit Register Variables.

  • When -O0 is in use, the compiler allocates distinct stack memory for all variables that do not have the register storage-class specifier; if register is specified, the variable may have a shorter lifespan than the code would indicate and may never be placed in memory.

  • On some rare x86 targets, setjmp doesn’t save the registers in all circumstances. In those cases, GCC doesn’t allocate any variables in registers unless they are marked register.

For IAR compiler for ARM (source):

Honoring the register keyword (6.7.1)

User requests for register variables are not honored




回答3:


If an object of automatic storage duration never has its address taken, a compiler may safely assume that its value can only be observed or modified by code which uses it directly. In the absence of the register keyword, a compiler which generates code in single-pass fashion would have no way of knowing, given...

void test(int *somePointer)
{
  int i;
  for (int i=0; i<10; i+=2)
  {
    somePointer[i] = -1;
    somePointer[i+1] = 2;

whether the write to somePointer[i] might possibly write i. If it could, then the compiler would be required to reload i when evaluating somePointer[i+1]. Applying the register keyword to i would allow even a single-pass compiler to avoid the reload because it would be entitled to assume that no valid pointer could hold a value derived from the address of i, and consequently there was no way that writing somePointer[i] could affect i.

The register keyword could be useful, even today, if it were not interpreted as imposing a constraint that the address of an object cannot be exposed to anything, but rather as inviting compilers to assume that no pointer derived from an object's address will be used outside the immediate context where the address was taken, and within contexts where the address is taken the object will be accessed only using pointers derived from address. Unfortunately, the only situations the Standard permits register qualifiers are those where an object's address is never neither used nor exported to outside code in any fashion--i.e. cases which a multi-pass compiler could identify by itself without need for the qualifier.

The register keyword could be useful, even with modern compilers, if it invited compilers to--at their leisure--treat any context where a register-qualified object's address is taken (e.g. get_integer(&i);) using the pattern:

{
  int temp = i;
  get_integer(&temp);
  i = temp;
}

and to assume that a register-qualified object of external scope will only be accessed in contexts which either explicitly access the object or take its address. At present, compilers have very limited ability to cache global variables in registers across pointer accesses involving the same types; the register keyword could help with that except that compilers are required to treat as constraint violations all the situations where it could be useful.



来源:https://stackoverflow.com/questions/43475229/is-it-useless-to-use-the-register-keyword-with-modern-compilers-when-optimizi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!