2
\$\begingroup\$

This question is to clarify my doubt against this register storage class.

  1. when a variable is register qualified ,compiler puts the variable in a cpu register other than RAM for ease of access. so there are registers available on a CPU for general purpose (allows user to use it freely)? ( I'm not going to ask does it mean any SFR (i don't like to change the meaning of SFR )

    On a PIC MCU(maybe applicable to base line only) SFRs and general purpose registers (which is the only RAM I believe) exist together. Here I cant think of any optimization with a 'register' or there is ?

  2. Could someone explain how does it achieve the optimization in terms of speed (of access) on other architectures?

  3. Or the above questions all out of many misconceptions?

\$\endgroup\$
  • 4
    \$\begingroup\$ AFAIK "register" is just a very loose recommendation for the compiler; it doesn't mean the compile has to put the variable into a register. Most of the time the compiler knows better where to put the variable and uses registers where possible anyhow. So often the keyword has not effect. \$\endgroup\$ – Curd Oct 11 '13 at 10:05
  • \$\begingroup\$ "uses registers where possible anyhow" could you please elaborate in terms of which registers and why is it not possible? \$\endgroup\$ – raforanz Oct 11 '13 at 10:10
  • 1
    \$\begingroup\$ I don't know the detailed internals of PIC MCUs but in general processors have a limited number of registers they can use for operations (e.g. adding). If a function uses many local variables not all of them can be held in registers and at least some need to be located in external RAM. The compiler has some sophisticated strategy to determine which variables to keep in registers (e.g. the ones used most often) and which not (e.g. the ones that need to bee in memory anyhow because they are refered to by pointers). \$\endgroup\$ – Curd Oct 11 '13 at 10:26
  • \$\begingroup\$ @Curd why didn't you put that comment in Answers? \$\endgroup\$ – raforanz Oct 11 '13 at 10:30
  • \$\begingroup\$ ok, I copied the comment also into an answer (I didn't put it there first because I wasn't sure if it answers enough of the question :-) \$\endgroup\$ – Curd Oct 11 '13 at 10:45
3
\$\begingroup\$

Your question is a little confused, but perhaps this will help clear it up.

There are two areas to consider:

  • whether the execution core can directly operate on items in memory
  • the speed of operations on memory

Small embedded microcontrollers

These small microcontrollers have no external RAM. All RAM is internal, but some of it is used for specific things like registers.

For example, the Microchip PICs you mention have a "W" register. This is just in normal RAM like everything else, but instructions with two operands usually require one of them to be in the W register.

This greatly simplifies the design of the microcontroller at the electronics level and keeps costs/power low. It also has other benefits like predictable timing (in cycles) for instructions.

This is why you will see instructions that load W with a value, operate on it and then copy it back from W to elsewhere in memory. The compiler uses the register because it has to.

Larger processors

Other processors (CPUs) such as x86/64 have external RAM which is a big difference. Notice now a "register" means something very different because we have different types of memory.

External to the CPU is large quantities of RAM, internal to the CPU are a number of smaller blocks of memory. Some of these are storage registers that hold an amount of data, usually the same as the data width of the architecture. So for a 32 bit Intel processor the registers (such as EAX, EBX etc) are 32 bits wide.

These processors have more complicated instructions that can often operate on either registers or external RAM. Data for an instruction does not always need to be in a register. Therefore why would we bother? The answer is speed. Where there is a choice the compiler will use registers to reduce execution time.

These complicated processors have different access times for different types of memory. Registers that are on the CPU die are very quick to access. So if you have a variable which is in constant use throughout some code it makes sense to load it into a register, operate on it repeatedly and then copy it back to external RAM when finished.

\$\endgroup\$
  • \$\begingroup\$ I should not have forgotten the differences between a micro processor and a micro controller \$\endgroup\$ – raforanz Oct 11 '13 at 11:01
  • \$\begingroup\$ "For example, the Microchip PICs you mention have a "W" register. This is just in normal RAM like everything else" you missed a 'not' I think. \$\endgroup\$ – raforanz Oct 11 '13 at 11:05
  • \$\begingroup\$ Actually this depends. On some devices (I checked 16F) it is only accessible through instructions like MOVF x,W/MOVWF but on others (18F25K22) it is also mapped to a location in RAM that you can access. However - on all devices it acts like a general purpose accumulator register no matter how it is presented. \$\endgroup\$ – David Oct 11 '13 at 12:26
1
\$\begingroup\$

It would depend on which compiler is used, but you are right; for a processor which has nothing but registers, with access time unchanged no matter which register (no bank selection), then the qualification should be meaningless.

If bank selection is needed, then the compiler should confine the variable to the same bank as is currently in use at execution time.

But why speculate? You can check this by comparing the assembly and machine code output of the compiler, with and without a register qualification in an interesting place. If you see no difference, you know that the qualification is not currently needed. Doesn't mean it won't be useful later though.

(You can use difference detecting programs, acting on the assembly output. Exactly which programs to use depends on your preference. I would use diff or meld on Linux, for example.)

\$\endgroup\$
  • \$\begingroup\$ WinMerge and DiffMerge are half decent on Windows, Meld also works (decently) on Windows but it's not as good as its Linux counterpart. \$\endgroup\$ – NickHalden Oct 11 '13 at 19:13
4
\$\begingroup\$

AFAIK "register" is just a very loose recommendation for the compiler; it doesn't mean the compiler has to put the variable into a register. Most of the time the compiler knows better where to put the variable and uses registers where possible anyhow. So often the keyword has not effect.

I don't know the detailed internals of PIC MCUs but in general processors have a limited number of registers they can use for operations (e.g. adding). If a function uses many local variables not all of them can be held in registers and at least some need to be located in external RAM. The compiler has some sophisticated strategy to determine which variables to keep in registers (e.g. the ones used most often) and which not (e.g. the ones that need to bee in memory anyhow because they are refered to by pointers).

\$\endgroup\$
1
\$\begingroup\$

Depending on the processor, accessing data in registers may be done with a shorter instruction than accessing data in memory. That alone can speed up execution of that instruction, besides saving program memory. The speed gain can be especially beneficial inside a loop. Some operations can only work on a register or between two registers. Having a variable in a register at that time is a necessity. If it can be kept in the register, two operations can be saved (loading the register from memory and storing the new value back to memory). Most compilers are better and more thorough than most programmers at figuring out how best to benefit by using the limited number of registers for the purpose. Examine the assembler output from same code with no register specifiers, compiled both with and without optimization turned on to see what the optimizer does and doesn't assign to registers.

\$\endgroup\$
0
\$\begingroup\$

Nowadays, many compilers have data-flow analysis algorithms that can use registers more efficiently than would be possible with an expert programmer putting each variable either into a register or into memory, since compilers may decide that variables should live in registers for some parts of their lifetime and in memory for other parts. As such, the primary function of the register keyword is to instruct the compiler that it should forbid any attempt to take the address of a particular variable. Taking the address of a variable generally implies that it must not be kept in a register across function calls, but for variables whose address is not taken the register keyword need not have any effect when the compiler is deciding when to keep variables in registers.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.