4 ms·
It's so much fun to explore why certain instances of undefined behavior do what they do. I never thought of this as being a possible effect of using uninitiali
by Suncho 14y ago
It's so much fun to explore why certain instances of undefined behavior do what they do. I never thought of this as being a possible effect of using uninitialized variables.
Logically, you're doing two things. You're negating the bool and then you're testing that negated value. This is what's expressed in the code generated from the non-optimized version. In the optimized version, the compiler has optimized this into a single jne instruction. I can understand why they wouldn't want to do it for non-optimized builds.
It sounds like gcc always uses xor for negating bools. If all you're doing is negating a bool, it's just a single instruction that involves no branching. It could be the fastest way.
I wonder what the fastest way to negate (boolean-wise) a value other than a bool would be. Maybe you just do a test and then set the value based on a xor of the zero flag.
- pbsd 14y ago> I wonder what the fastest way to negate (boolean-wise) a value other than a bool would be. Maybe you just do a test and then set the value based on a xor of the zero flag. Probably "NOT reg". Exists in most CPU architectures, and is generally smaller (in variable-size instruction sets) than "XOR reg, immed".
- drv 14y agoNOT, at least in x86, is bitwise, so it won't do the right thing for values other than 0 and ~0 (-1).
- pbsd 14y agoOh, I misunderstood. Thought it the point was to make it bitwise. In that case, it is very architecture-dependent. In x86, you can use TEST coupled with SETcc or CMOV for microarchitectures where branch mispredictions are very costly (P4 comes to mind). If not, and the result is not random, you're better off with a branch. Another trick is to use the carry flag, i.e., NEG reg; MOV reg, 0; ADC reg, 0. This works for all 386-compatible processors and is reasonably fast.