It's hard to tell if you ask asking if subtraction is fast then negation in a general sense, or in this specific case of implementing negation via subtraction from zero. I'll try to answer both.
General Case
For the general case, on most modern CPUs these operations are both very fast: usually each only taking a single cycle to execute, and often having a throughput of more than one per cycle (because CPUs are superscalar). On all recent AMD and Intel CPUs that I checked, both sub
and neg
execute at the same speed for register and immediate arguments.
Implementing -x
As regards to your specific question of implementing the -x
operation, it would usually be slightly faster to implement this with a dedicated neg
operation than with a sub
, because with neg
you don't have to prepare the zero registers. For example, a negation function int neg(int x) { return -x; };
would look something like this with the neg
instruction:
neg:
mov eax, edi
neg eax
... while implementing it terms of subtraction would look something like:
neg:
xor eax, eax
sub eax, edi
Well ... sub
didn't come out looking at worse there, but that's mostly a quirk of the calling convention and the fact that x86 uses a 1 argument destructive neg: the result needs to be in eax
, so in the neg
case 1 instruction is spent just moving the result to the right register, and one doing the negation. The sub
version takes two instructions to perform the negation itself: one to zero a register, and one to do the subtraction. It so happens that this lets you avoid the ABI shuffling because you get to choose the zero register as the result register.
Still, this ABI related inefficiency wouldn't persist after inlining, so we can say in some fundamental sense that neg
is slightly more efficient.
Now many ISAs may not have a neg
instruction at all, so the question is more or less moot. They may have a hardcoded zero register, so you'd implement negation via subtraction from this register and there is no cost to set up the zero.