Live data from Hacker News

XOR'ing a register with itself is the idiom for zeroing it out. Why not sub?

devblogs.microsoft.com

41–50 of 231 posts

Re: XOR'ing a register with itself is the idiom for zeroing it out. Why not sub?

#41
post #34
post #10

Once an instruction has an edge, even if only extremely slight, that’s enough to tip the scales and rally everyone to that side. And this, interestingly, is why life on earth uses left-handed amino acids and right-handed sugars .. and why left handed sugar is perfect for diet sodas.

You still need to explain why this case creates a positive feedback loop rather than a negative one. I mean left/right fuel intakes in cars and male/female ratios somehow tend to balance at 50/50.

Wrt amino acids and sugars I personally don't have to explain as a good many others have already.

eg: For one, Isaac Asimov in the 1970s wrote at length on this in his role as a non fiction science writer with a Chemistry Phd

> male/female ratios somehow tend to balance at 50/50.

This is different to the case of actual right handed dominance in humans and to L- Vs R- dominance in chirality ...

( Men and women aren't actual mirror images of each other ... )

Re: XOR'ing a register with itself is the idiom for zeroing it out. Why not sub?

#42

Earlier quoted context omitted.

It's like 0.5 cycles vs 0.9 cycles. So both are 1 cycle, considering synchronization.

But energy consumption could be different for this hypothetical 0.5 and 0.9.

Energy consumption wasn't really a concern when the idiom developed. I don't think people really cared about the energy consumption of instructions until well into the x86-64 era.

Re: XOR'ing a register with itself is the idiom for zeroing it out. Why not sub?

#43
post #4

The obvious answer is that XOR is faster. To do a subtract, you have to propagate the carry bit from the least-significant bit to the most-significant bit. In XOR you don't have to do that because the output of every bit is independent of the other adjacent bits. Probably, there are ALU pipeline designs where you don't pay an explicit penalty. But not all, and so XOR is faster. Surely, someone as awesome as Raymond C…

I would be surprised if modern CPUs didn't decode "xor eax, eax" into a set of micro-ops that simply moves from an externally invisible dedicated 0 register. These days the x86 ISA is more of an API contract than an actual representation of what the hardware internals do.

Zero micro ops to be precise, that’s handled entirely at the register rename stage with no data movement.

Re: XOR'ing a register with itself is the idiom for zeroing it out. Why not sub?

#44
post #35

It might be because XOR is rarely (in terms of static count, dynamically it surely appears a lot in some hot loops) used for anything else, so it is easier to spot and identify as "special" if you are writing manual assembly.

XOR appears a lot in any code touching encryption. PS. What is static vs dynamic count ?

Static count - how many times an instruction appears in a binary (or assembly source).

Dynamic count - how many times an opcode gets executed.

I. e. an instruction that doesn't appear often in code, but comes up in some hot loops (like encryption) would have low static and high dynamic.

Re: XOR'ing a register with itself is the idiom for zeroing it out. Why not sub?

#45
post #27
post #15

"Bonus bonus chatter: The xor trick doesn’t work for Itanium because mathematical operations don’t reset the NaT bit. Fortunately, Itanium also has a dedicated zero register, so you don’t need this trick. You can just move zero into your desired destination." Will remember for the next time I write asm for Itanium!

Quite a few architectures have a dedicated 0 register.

Yep. The XOR trick - relying on special use of opcode rather than special register - is probably related to limited number of (general purpose) registers in typical '70 era CPU design (8080, 6502, Z80, 8086).

Re: XOR'ing a register with itself is the idiom for zeroing it out. Why not sub?

#46
post #4

The obvious answer is that XOR is faster. To do a subtract, you have to propagate the carry bit from the least-significant bit to the most-significant bit. In XOR you don't have to do that because the output of every bit is independent of the other adjacent bits. Probably, there are ALU pipeline designs where you don't pay an explicit penalty. But not all, and so XOR is faster. Surely, someone as awesome as Raymond C…

Because he is explicitly talking about x86 - maybe you missed that.

Re: XOR'ing a register with itself is the idiom for zeroing it out. Why not sub?

#47
Relatedly, there's a steganographic opportunity to hide info in machine code by using "XOR rax,rax" for a "zero" and "SUB rax,rax" for a "one" in your executable. Shouldn't be too hard to add a compiler feature to allow you to specify the string you want encoded into its output.

Re: XOR'ing a register with itself is the idiom for zeroing it out. Why not sub?

#48
post #32
post #27

Earlier quoted context omitted.

Quite a few architectures have a dedicated 0 register.

indeed. riscv for instance. also, afaik, xor’ing is faster. i would assume that someone like mr. raymond would know…

> afaik, xor’ing is faster

Even tiny tiny CPUs can do sub in one cycle, so I doubt that. On super-scalar CPUs xor and sub are normally issued to the same execution units so it wouldn't make a difference there either.

Re: XOR'ing a register with itself is the idiom for zeroing it out. Why not sub?

#49

Earlier quoted context omitted.

What's SMT in this context?

Simultaneous Multi-Threading (hyper-threading as Intel calls it). I'm not a cpu guy, but I think the ALU used for subtraction would be a more valuable resource to leave available to the other thread than whatever implements a xor. Hence you prefer to use the xor for zeroing and conserve the ALU for other threads to use.

I don't think that's how it works.

- Normally ALU implements all "light" operations (i. e. add/sub/and/or/xor) in a single block, separating them would result in far more interconnect overhead. Often, CPUs have specialized adder-only units for address generation, but never a xor-specialized block.

- All CPUs that implement hyper-threading also optimize a XOR EAX,EAX into MOV EAX,ZERO/SET FLAGS (where ZERO is an invisible zero register just like on Itanium and RISCs). This helps register renaming and eliminates a spurious dependency.

- The XOR trick is about as old as 8086 if not older.

Re: XOR'ing a register with itself is the idiom for zeroing it out. Why not sub?

#50

Back in the stone ages XOR ing was just 1 byte of opcode. Habbits stick. In effect XORing is no longer faster since a long time.

Depending on what's stone-age for you, a SUB with a register was also only one byte, and was the same cost as XOR, at least in the Intel/Zilog lineage all the way back to the 70s ;)
Post reply on HN