Microarchitectural zeroing of a register via the register renamer: performance versus a mov?

Executive summary: You can run up to four xor ax, ax instructions per cycle as compared to the slower mov immediate, reg instructions.

Details and references:

Wikipedia has a nice overview of register renaming in general: http://en.wikipedia.org/wiki/Register_renaming

Torbj¨orn Granlund's timings for instruction latencies and throughput for AMD and Intel x86 processors are at: http://gmplib.org/~tege/x86-timing.pdf

Agner Fog nicely covers the specifics in his Micro-architecture study:

8.8 Register allocation and renaming

Register renaming is controlled by the register alias table (RAT) and the reorder buffer (ROB) ... The µops from the decoders and the stack engine go to the RAT via a queue and then to the ROB-read and the reservation station. The RAT can handle 4 µops per clock cycle. The RAT can rename four registers per clock cycle, and it can even rename the same register four times in one clock cycle.

Special cases of independence

A common way of setting a register to zero is by XOR'ing it with itself or subtracting it from itself, e.g. XOR EAX,EAX. The Sandy Bridge processor recognizes that certain instructions are independent of the prior value of the register if the two operand registers are the same. This register is set to zero at the rename stage without using any execution unit. This applies to all of the following instructions: XOR, SUB, PXOR, XORPS, XORPD, VXORPS, VXORPD and all variants of PSUBxxx and PCMPGTxx, but not PANDN etc.

Instructions that need no execution unit

The abovementioned special cases where registers are set to zero by instructions such as XOR EAX,EAX are handled at the register rename/allocate stage without using any execution unit. This makes the use of these zeroing instructions extremely efficient, with a throughput of four zeroing instructons per clock cycle.


The biggest performance cost in your zeroing is hidden in this sentence:

Basically what it happening is that I would like to zero a register within a loop depending on a condition

That sentence implies a branch. Even if the branch is correctly predicted it will still likely cost more than zeroing a register.

As for register renaming...

In an OutOfOrder (OOO) CPU every time you write to a register the CPU gives you a new register. If you executed these three instructions:

xor eax,eax
add eax,eax
add eax,1

then for the first instruction the CPU (if it's a recent Intel CPU anyway) just updates its mappings to say that eax now refers to an internal zero register. On the first add it reads from eax (twice, since it is used twice as an input) and then updates its mapping to point to a new register and writes the result to that register. The same thing happens with the second add. So, over the course of these three instructions the eax register is changed to point to three different physical registers.

Why? Because of this:

mov eax,[esi]    ; Load from esi
add eax, 1
mov [esi], eax   ; Store to esi
mov eax,[esi+4]  ; Load from esi+4
add eax, 1
mov [esi+4], eax ; Store to esi+4

On an OOO processor one of the main restrictions on performance is dependencies. Instructions one to three must execute in order. Instructions four to six must execute in order. But there are no dependencies between those two blocks. So, one-to-three and four-to-six can execute in parallel. But, they all refer to eax.

No problem. Register renaming solves this. The first and fourth instructions execute simultaneously. The CPU creates a separate mapping for eax for each point in the instruction flow, and subsequent instructions operate on these renamed registers. This allows the two blocks of instructions to execute fully in parallel.

This is actually fiendishly complicated for all sorts of reasons, but it works, and it is one of the main things that allows modern CPUs to run so fast.

Anyway, long-story short, "xor eax,eax" never even executes, and that is cool. That optimization could be applied to any instruction that always produces zero or always produces ones, or whatever, but Intel is only going to spend the transistors to do this when it matters. I guess xorpd doesn't make the cut, yet.

I blogged about this (http://randomascii.wordpress.com/2012/12/29/the-surprising-subtleties-of-zeroing-a-register/) because I thought it was cool. I also liked the idea that 'add' and 'sub', which are mostly identical instructions, can have slightly or vastly different performance because of this behavior, albeit only in the case where a register is subtracted from itself.