I'm on Gentoo Linux, my the use flags affecting GCC are "fortran" and "nls". I have tried the following with -O2. If I write a piece of code that looks like one of these : example 1 : a = (b == 1 ? 1 : 0); example 2 : a = (b == 1 ? 2 : 0); example 3 : if( b == 1 ) a = 2; else a = 0;
The compiler optimizes it by using the sete/setne instruction instead of a potentially slow conditional jump and then doing a bit shift if necessary. However, while code like example 4 : a |= (b == 1 ? 1 : 0) example 5 : if( b == 1 ) a |= 1; is optimized the same way, code like example 4 : a |= (b == 1 ? 2 : 0) example 5 : if( b == 1 ) a |= 2; is not optimized with a sete/setne, a conditional jump is used. Since there is a workaround to make GCC use a sete/setne workaround : t = (b == 1 ? 2 : 0); // or if( b == 1 ) t = 2; else t = 0; a |= 2; I could compare the performance of sete/setne like operations vs conditional jumps on my AMD Ahlon XP 1700+. It turns out that, without -march=athlon-xp, the workaround, using a if() or a ?: as constant speed that is faster than code like example 4 and 5, except when the probability is very close to 1/2. The further from 1/2, the slower, on the extreme, it can be more than 2x slower. At 1/2, the conditional jump is faster, but not by much. For some reason, code like example 4 is slower than code like example 5. With -march=athlon-xp, code like example 5 and the workaround behaves the same, but code like example 4 as a constant time that is however slower than the workaround but faster than most other cases when compiled without -march=athlon-xp. Disassembly shows that it is using a conditional move. -- Summary: Optimization flaw on conditionnal set of a bit. Product: gcc Version: 3.4.5 Status: UNCONFIRMED Severity: enhancement Priority: P3 Component: c++ AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: dominic dot quiet at gmail dot com http://gcc.gnu.org/bugzilla/show_bug.cgi?id=26656