I am writing an embedded C code. Which if condition would be faster/optimized:
if (a == false)
{
Some code
}
OR
if (a != true)
{
Some code
}
CodePudding user response:
Reading this question, the first thing that came to my mind is "That's ridiculous, the compiler knows better and will optimize it anyway, right?"
Well, turns out I was wrong, here is how MSVC /O2 compiles it:
With if (a == false)
:
84 C9 | test cl, cl
With if (a != true)
:
80 F9 01 | cmp cl, 1
Well, that's weird. Mike Nakis explained the difference between cmp
and test
in this answer. And Peter Cordes commented below:
There can be a perf difference on Intel Core2 or Nehalem, where TEST can macro-fuse with more flavours of JCC than CMP. e.g. Core2 and Nehalem can macro-fuse test eax,eax / js, but not cmp eax,0 / js. Nehalem can macro-fuse cmp eax,0 / jl, though. (Core2 can't, but Core2 can only macro-fuse at all in 32-bit mode).
I believe this is true, test
can be faster on some CPUs, but I don't believe its effect is measurable in practical scenarios.
Weirdly enough, for GCC, both -O2
and -O3
prefer cmp
over test
and will produce the same output for both cases.
Related: Test whether a register is zero with CMP reg, 0 vs OR reg, reg
CodePudding user response:
If a
is of type bool
, you won't be able to spot a difference — probably even if you look at the assembly language code. Certainly, it is unlikely to be a measurable difference, especially if Some code
is more than a single instruction (or thereabouts). But only measurement or scrutiny of the assembly language can show you the difference.
If a
is of type int
(or any other non-bool
type), the conditions have different meanings and at most one of them is correct. The first is equivalent to a == 0
; the second is equivalent to a != 1
. Unless a
is restricted to the range 0
and 1
, the results are different when a
is 2
, for example.
The idiomatic test would be if (!a)
and that works the same for bool
and non-bool
types. You probably won't be able to spot any difference here, either.
CodePudding user response:
Same thing. Or just do if (!a) { /* code */ }