The reason becomes very apparent if you write out the assembly necessary to compile the xor, vs what is needed to compile a classic swap.
The xor would look something like:
load $1, a load $2, b xor $3, $1, $2 xor $4, $3, $2 xor $5, $4, $3 store b, $4 store a, $5
where as the classic swap would look something like this:
load $1, [a] load $2, [b] store b, $1 store a, $2
which is much better.
If you take the pipeline into account, then the difference between the swap and the xor can be huge because their is high level of dependence between the instructions.
On a theoretical classic 5-stage pipeline, the swap approach ends up needing about 10 cycles, where as the xor needs about 18.
In a real processor the difference would probably be much worse.
However, with a good register allocator and inlined functions, your point becomes even stronger. The compiler can simply remove all instructions associated with the naieve swapping version, and simply record that before the swap %eax holds b, and after it, %eax now holds a. (Even the most naieve of code generators will do this sort of thing if the values in the swap don't fall outside of a basic block). The xors are far harder to optimize.
Here's the general proof:
a ^= b (a = a ^ b, b = b)
b ^= a (a = a ^ b, b = b ^ (a ^ b) = a)
a ^= b (a = b ^ (a ^ b) = b ,b = a)
Now, let's replace all references initial values with constant c:
a ^= b (a = c ^ c = 0, b = c)
b ^= a (a = 0, b = c ^ 0 = c)
a ^= b (a = c ^ 0 = c, b = c)
Notice that at the end, you still end up with a = b = c. There are plenty of reasons not to use this approach, but that ain't one of them.
int swap(int * a, int * b)
{
(*a)^=(*b);
(*b)^=(*a);
(*a)^=(*b);
}
int x = 15;
int *y = &x;
int *z = &x;
swap(y,z); //Now *y == 0 fast_swap_values(unsigned long*, unsigned long*)
Users of the function could accidentally pass in the same addresses.(JWZ's subtitle: "Why Cooperation With RMS Is Impossible".)
first only works if a is a different var than b
second it can be much slower than typical swap...
and finaly, it isn't clear what it does if your code is for others to read