Hi all, Today I noticed something strange with the way gcc optimises ternary operations in c (and c++). Consider the following example where I call foo(int) passing the clamped value of (s0, s1, s2):
/*----------------------------------------------------------------------------*/ #include <algorithm> extern "C" { void foo(int i); } void bar(int s0, int s1, int s2) { foo(std::max(s0, std::min(s1, s2))); } /*----------------------------------------------------------------------------*/ When I compile the above class with -O1 -S, the generated assembly contains 2 conditional moves and 0 branches: stmfd sp!, {r3, lr} .save {r3, lr} cmp r2, r1 movge r2, r1 cmp r0, r2 movlt r0, r2 bl foo(PLT) ldmfd sp!, {r3, pc} If I replace the call to foo with one of the following: foo(std::min(std::max(s0, s1), s2)); foo(s1 < s2 ? (s1 > s0 ? s1 : s0) : s2); foo(s1 < s2 ? (s1 < s0 ? s0 : s1) : s2); foo(s1 > s2 ? s2 : (s1 > s0 ? s1 : s0)); foo(s1 > s2 ? s2 : (s1 < s0 ? s0 : s1)); the generated output is the same. On the other side, when I replace the foo call with one of the following: foo(s0 < s1 ? (s2 < s1 ? s2 : s1) : s0); foo(s0 < s1 ? (s2 > s1 ? s1 : s2) : s0); foo(s0 > s1 ? s0 : (s2 < s1 ? s2 : s1)); foo(s0 > s1 ? s0 : (s2 > s1 ? s1 : s2)); The generated assembly contains 1 branch instruction + 2 conditional moves: stmfd sp!, {r3, lr} .save {r3, lr} cmp r0, r1 bge .L2 cmp r1, r2 movlt r0, r1 movge r0, r2 .L2: bl foo(PLT) ldmfd sp!, {r3, pc} I expected all the different combinations of "clamp" should generate the same assembly. Is there a reason for this? Is this a GCC "bug"? Thanks Andrea