views:

252

answers:

7

I'm wondering if a pointer may point to a cpu register since in the case it may not, using reference instead of pointer where possible would give compiler opportunity to do some optimizations because the referenced object may reside in some register but an object pointed to by a pointer may not.

+2  A: 

I think what you meant to say is whether an integral value referred to by a reference reside in a register.

Usually, most compilers treat references the same way as pointers. That is to say references are just pointers with special "dereference" semantics built in. So, sadly there usually is no optimization unlike with integral values that can fit into registers. The only difference between a reference and a pointer is that a reference must (but not enforced by the compiler) refer to a valid object, whereas a pointer can be NULL.

Michael Goldshteyn
+1  A: 

In many(if not most or all) implementations a reference is deep inside implemented via a pointer. So I think that doing it via a pointer or reference is pretty much irrelevant for an optimizer.

Armen Tsirunyan
+4  A: 

In general, CPU registers do not have memory addresses, though a CPU architecure could make them addressable (I;m not familar with any - if someone knows of one, I'd appreciate a comment). However, there's no standard way in C to get the address of a register. In fact if you mark a variable with the register storage class you aren't permitted to take that variables address using the & operator.

The key issue is aliasing - if the compiler can determine that an object isn't aliased then it can generally perform optimizations (whether the object is accessed via a pointer or a reference). I don't think you'll get any optimization benefit using a reference over a pointer (in general anyway).

However if you copy the object into a local variable, then the compiler can make an easier determination that there's no aliasing of the local assuming you don't pass the temporaries address around. This is a case where you can help the compiler optimize; however if the copy operation is expensive, it might not pay off in the end.

For something that would fit in a CPU register, copying to a temp is often a good way to go - compilers are great at optimizing those to registers.

Michael Burr
Does the C or C++ standard explicitly say that an object declared register cannot be taken its address of?
Armen Tsirunyan
@Armen: Yes. @MichaelBurr: Microchip PICs have the actual CPU registers (e.g. status, program counter, working register, index registers) mapped to the lower 12 bytes of every memory bank. http://ww1.microchip.com/downloads/en/DeviceDoc/41413A.pdf p. 23
Nick T
Michael Burr
@Nick T: thanks for the pointer (`**rimshot**`).
Michael Burr
@Michael: Thank you, I never knew it. But do the modern compilers ACTUALLY put a register object in a register, 'cause I have heard they ignore the register hint completely and decide what to put in a register themselves
Armen Tsirunyan
@Armen: I have also heard about compiler essentially ignoring the `register` keyword when determining how they allocate objects to registers - the standard certainly allows that behavior. I've also heard that you shouldn't use the keyword because you'll mess up the compiler's better judgment. I'm not sure which extreme is more true. The truth is probably that it depends on which compiler and which options you're using.
Michael Burr
Every time I've tried using the `register` keyword with compilers I commonly use (all embedded MCU stuff), they just ignore it. You can sometimes force the issue with embedded assembly, but the few times I've tried I made it worse. Some MCUs it would be a joke, e.g. the HCS08 has 3 8-bit registers not counting pointers/counters/status, but there you can use directives to force variable allocation in faster parts of RAM
Nick T
@Armen: As far as I know the only modern benefit to the register keyword is it clarifies intent and makes it a bug to accidentally take the address of the object. So it is sort of like using const.
Zan Lynx
You could think of the microchip pic (pic12, pic16) registers as an address as well. The ram/memory is collectively called the f register. And the code might refer to them by their address for the special registers, the pc itself is addressable. A stack based processor like the zpu http://opensource.zylin.com/zpu.htm where there are no registers. Have not studied the zpu that closely just happened to have seen it and quickly saw that it was stack based. I am wanting to say the 8051 but cant find it saying that, I think there is another I have used but cannot remember.
dwelch
A: 

Pointer points to memory locations. So it is not possible to access CPU registers using pointers. References are less powerful version of pointers (you can't perform arithmetic on references). However compilers generally put variables into registers to perform operations. For example, compiler may put a loop counter into one of CPU registers for quick access. Or may put function parameters that don't take much space in registers. There is a keyword in C that you can use to request compiler to put certain variable into CPU register. The keyword is register:

for (int i = 0; i < I; i++)
    for (int j = 0; j < J; j++)
        for (register int k = 0; k < K; k++)
        {
            // to do
        }
Donotalo
Some architectures do have memory mapped registers, so your answer is not strictly correct.
Paul R
The `register` keyword is essentially an hollow request to the compiler that it's free to totally and silently ignore.
Nick T
@Paul R: i agree. but i think it is the closest possible solution in C.
Donotalo
@Nick T: yes, i stated in the post: "...to request compiler..."
Donotalo
+1  A: 

When a reference is passed to a function, the compiler will probably implement it as a hidden pointer - so changing the type won't matter.

When a reference is created and used locally, the compiler may be smart enough to know what it refers to and treat it as an alias to the referenced variable. If the variable is optimized to a register, the compiler would know that the reference is also that same register.

A pointer will always need to point to a memory location. Even on the odd architecture that gives memory locations to its registers, it seems unlikely that the compiler would support such an operation.

Edit: As an example, here is the generated code from Microsoft C++ with optimizations on. The code for the pointer and a passed reference are identical. The parameter passed by value for some reason did not end up in a register, even when I rearranged the parameter list. Even so, once the value was copied to a register both the local variable and the local reference used the same register without reloading it.

void __fastcall test(int i, int * ptr, int & ref)
{
_i$ = 8                         ; size = 4
_ref$ = 12                      ; size = 4
?test@@YIXHPAHAAH@Z PROC                ; test, COMDAT
; _ptr$ = ecx

; 8    :    global_int1 += *ptr;

    mov edx, DWORD PTR [ecx]

; 9    : 
; 10   :    global_int2 += ref;

    mov ecx, DWORD PTR _ref$[esp-4]
    mov eax, DWORD PTR _i$[esp-4]
    add DWORD PTR ?global_int1@@3HA, edx    ; global_int1
    mov edx, DWORD PTR [ecx]
    add DWORD PTR ?global_int2@@3HA, edx    ; global_int2

; 11   : 
; 12   :    int & ref2 = i;
; 13   :    global_int3 += ref2;

    add DWORD PTR ?global_int3@@3HA, eax    ; global_int3

; 14   : 
; 15   :    global_int4 += i;

    add DWORD PTR ?global_int4@@3HA, eax    ; global_int4
Mark Ransom
A: 

Michael Burr is correct. CPU registers do not have memory addresses.

renai
Unless they're mapped to memory, like in Microchip PICs
Nick T
Also the Z8 had banks of memory-mapped registers IIRC.
Paul R
A: 

I would say generally not. As mentioned in an above comment there are some processors where you can address a register in memory space, but that is probably a bad idea (unless the chip was designed for you to program it that way).

It is more like the opposite of what you are asking actually happens. The optimizers can see what you are doing with an pointer and what it points to and depending on the architecture may not actually use a register for the pointer and a register to hold what it points to but for example may hardcode the address into the instruction using no registers at all. May load the value pointed to into a register but use a register for the address or use it longer than it takes to get the value. Sometimes it is not that efficient, it may save the value in a register to ram just so it can read it back into a register using its address, when changing the code would avoid that two step. It depends heavily on the program/code and the instruction set and compiler.

So instead of trying to address the register to try to get some optimization, know the compiler and target and know when it is better to use pointers or arrays or values, etc. some constructs work well on most processors and some only work well on one but bad on others.

dwelch