Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is comparing to zero faster than comparing to any other number?

Is

if(!test)

faster than

if(test==-1)

I can produce assembly but there is too much assembly produced and I can never locate the particulars I'm after. I was hoping someone just knows the answer. I would guess they are the same unless most CPU architectures have some sort of "compare to zero" short cut.

thanks for any help.

like image 474
deanresin Avatar asked Mar 17 '14 21:03

deanresin


People also ask

Which comparison operator is faster?

Some processors are quicker when comparing against zero. So > 0 might be faster than >= 1 , as an example. @Simple A decent compiler will replace >= 1 with > 0 if it's faster.

Does <= take more time than?

Do you think operator < is faster than <= in C/C++? No, the operator < takes same time to execute as operator <= takes. Both operators execute similarly and take same execution time to perform the execution of instructions.

Is integer comparison faster than string comparison?

Usually integers are faster. If the strings are really short (one character), they might be faster.


3 Answers

Typically, yes. In typical processors testing against zero, or testing sign (negative/positive) are simple condition code checks. This means that instructions can be re-ordered to omit a test instruction. In pseudo assembly, consider this:

Loop:
  LOADCC r1, test // load test into register 1, and set condition codes
  BCZS   Loop     // If zero was set, go to Loop

Now consider testing against 1:

Loop:
  LOAD   r1, test // load test into register 1
  SUBT   r1, 1    // Subtract Test instruction, with destination suppressed
  BCNE   Loop     // If not equal to 1, go to Loop

Now for the usual pre-optimization disclaimer: Is your program too slow? Don't optimize, profile it.

like image 99
Sam Cristall Avatar answered Sep 25 '22 20:09

Sam Cristall


It depends.

Of course it's going to depend, not all architectures are equal, not all µarchs are equal, even compilers aren't equal but I'll assume they compile this in a reasonable way.

Let's say the platform is 32bit x86, the assembly might look something like

test eax, eax
jnz skip

Vs:

cmp eax, -1
jnz skip

So what's the difference? Not much. The first snippet takes a byte less. The second snippet might be implemented with an inc to make it shorter, but that would make it destructive so it doesn't always apply, and anyway, it's probably slower (but again it depends).

Take any modern Intel CPU. They do "macro fusion", which means they take a comparison and a branch (subject to some limitations), and fuse them. The comparison becomes essentially free in most cases. The same goes for test. Not inc though, but the inc trick only really applied in the first place because we just happened to compare to -1.

Apart from any "weird effects" (due to changed alignment and whatnot), there should be absolutely no difference on that platform. Not even a small difference.

Even if you got lucky and got the test for free as a result of a previous arithmetic instruction, it still wouldn't be any better.

It'll be different on other platforms, of course.

like image 36
harold Avatar answered Sep 26 '22 20:09

harold


On x86 there won't be any noticeably difference, unless you are doing some math at the same time (e.g. while(--x) the result of --x will automatically set the condition code, where while(x) ... will necessitate some sort of test on the value in x before we know if it's zero or not.

Many other processors do have a "automatic updates of the condition codes on LOAD or MOVE instructions", which means that checking for "postive", "negative" and "zero" is "free" with every movement of data. Of course, you pay for that by not being able to backward propagate the compare instruction from the branch instruction, so if you have a comparison, the very next instruction MUST be a conditional branch - where an extra instruction between these would possibly help with alleviating any delay in the "result" from such an instruction.

In general, these sort of micro-optimisations are best left to compilers, rather than the user - the compiler will quite often convert for(i = 0; i < 1000; i++) into for(i = 1000-1; i >= 0; i--) if it thinks that makes sense [and the order of the loop isn't important in the compiler's view]. Trying to be clever with these sort of things tend to make the code unreadable, and performance can suffer badly on other systems (because when you start tweaking "natural" code to "unnatural", the compiler tends to think that you really meant what you wrote, and not optimise it the same way as the "natural" version).

like image 26
Mats Petersson Avatar answered Sep 25 '22 20:09

Mats Petersson