Live data from Hacker News

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

devblogs.microsoft.com

161–170 of 231 posts

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

#161

Earlier quoted context omitted.

That's all true, but on any modern x86 processor both the single pair of gates for the xor and the 10 or so for a carry-bypass 64 bit wide subtraction both happen with a single clock cycle of latency so from a programmer's perspective they're the same in that sense. There's still an energy difference but its tiny compared to what even the register file and bypass network for the operation use, let along the OoO struc…

The question isn't whether they both take a clock cycle, but rather whether any future implementation of the ISA might ostensibly find some sort of performance advantage, even if none do right now. From that standpoint, xor seems like a safer bet.

Defacto standard, Compilers optimize for the CPU, CPU uarch is now optimizing for compilers

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

#162

XOR is a simple logic-gate operation. SUB would have to be an ALU operation. A one-bit adder (which is subtraction in reverse) makes signals pass through two gates. See https://en.wikipedia.org/wiki/Adder_(electronics) You need the 2 gates for adding/subtracting because you care about carry. So if you're adding/subtracting 8 bits, 16 bits, or more, you're connecting multiples of these together, and that carry has to…

That's all true, but on any modern x86 processor both the single pair of gates for the xor and the 10 or so for a carry-bypass 64 bit wide subtraction both happen with a single clock cycle of latency so from a programmer's perspective they're the same in that sense. There's still an energy difference but its tiny compared to what even the register file and bypass network for the operation use, let along the OoO struc…

The question is why one idiom won over the other, which happened a long time ago.

Because as the article notes on "any modern x86 processor" both xor r, r and sub r, r are handled by the frontend and have essentially no cost.

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

#163

XOR is a simple logic-gate operation. SUB would have to be an ALU operation. A one-bit adder (which is subtraction in reverse) makes signals pass through two gates. See https://en.wikipedia.org/wiki/Adder_(electronics) You need the 2 gates for adding/subtracting because you care about carry. So if you're adding/subtracting 8 bits, 16 bits, or more, you're connecting multiples of these together, and that carry has to…

That was what I guessed too, but according to the article Intel detected both.

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

#164
post #69
post #34

Earlier quoted context omitted.

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.

Regarding gender ratios: https://en.wikipedia.org/wiki/Fisher's_principle There's exceptions, but they tend to be colonial animals in the broadest sense e.g. how clownfish males are famously able to become female but each group has one breeding male and one breeding female at any given time*, or bees where the males (drones) are functionally flying sperm and there's only one fertile female in any given colony; or som…

Temperature-dependent sex determination may not be at equilibrium now but is not an exception to Fisher's principle. The temperature at which sex determination switches is variable based on the parent's genes, and it will try to re-equilibrate with the environment temperature to obtain 1:1 ratios just like in other animals.

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

#165

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.

Indeed this is the best explanation!

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

#166

I vaguely remember we used the XOR trick on processors other than Intel, so it may not be Intel-specific. In principle, sub requires 4 steps: 1. Move both operands to the ALU 2. Invert second operand (twos complement convert) 3. Add (which internally is just XOR plus carry propagate) 4. Move result to proper result register. This is absolutely not how modern processors do it in practice; there are many shortcuts, but…

You don't do twos complement negation for sub in an integer ALU. You do ones complement (A + ~B) and set the input carry to 1. The difference is that you don't need two carry propagations and therefore you can just add a fancy A + ~B function to the ALU.

Floating point is different because what matters is same sign or different sign (for same sign you cannot have cancellation and the exponent will always be the same or one than the largest input's. So the FP mantissa tends to use sign magnitude representation.

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

#168

Earlier quoted context omitted.

XOR can do everything in 1 cycle (which is hopefully far, far less than the clock). SUB-if done the simple way-has to take n cycles where n is the number of bits subtracted.

What do you mean by cycles? A ripple-carry adder needs to wait for the carry bits to ripple through yes, but there's no clock cycle involved.

Maybe they mean gate delays?

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

#169

Earlier quoted context omitted.

You may not be looking for the right thing. On the aforementioned CSP, the instruction that performed XOR was called "XR" and not "XOR". My source is firsthand knowledge; I was a CE and performed service calls on the System/34, System/36, 370, and 390. In any case, I am describing equipment built mostly in late 60s through the late 70s at IBM Rochester and Poughkeepsie. The IBM PC was developed by an entirely differe…

I don't doubt that this specific processor special-cased XOR (regardless of how it was called in the assembly language)! Merely pointing out that where both operations were available, there seems to have been a preference to use SUB instead, with some continuity from early business-oriented mainframes, to the 360, to the PC.

You probably would prefer to use SUB with fault-checking to clear registers in general-purpose code, and only use XOR in early startup (and perhaps fault handlers), where error checking has to be suppressed. So both observations seem to align well?

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

#170

Earlier quoted context omitted.

I’m not sure I understand what you mean by “waste 8 opcodes.”

They occupy 8 of the possible 256 byte values. Together, those five cases used about 15% of the space. Though I was forgetting one important case: MOV r,imm also used one-byte opcodes with the register index embedded. And it came in byte and word variants, so it used a further 16 opcodes bytes for a total of 56 one byte opcodes with register encoding.

Gotcha, thanks for clarifying. I was reacting to the word “waste” I guess. Surely, as you say, it consumes that opcode encoding space. Whether that’s a waste or not depends on a lot of other things, I suppose. I wasn’t necessarily thinking x86-specific in my original comment. But yea, if you try to zero every possible register and half-word register you would definitely consume lots of encoding space.
Post reply on HN