Four ways of coding a conditional assignment yields 1 conditional move using gcc 3.4.5 20051201 (Red Hat 3.4.5-2). gcc 4.0.2 20051130 (Red Hat 4.0.2-14.EL4) produces none. IMHO, four cmov's should have been produced. I further expect all four functions to generates the exact same code. All recent new commercial compilers tested generates four cmov's: - intel 8.1, 9.0, and 9.1 - pgi 5.2, 6.0, 6.1, and 6.2 - pathscale 2.1, 2.2, 2.3, 2.4 Version-Release number of selected component (if applicable): How reproducible: allways Steps to Reproduce: gcc -O2 -S if_conversion.c;egrep cmov\|^[a-d]: if_conversion.s Actual results: a: b: c: d: cmove %ecx, %esi Expected results: One cmovX per function, four in total. Here is the source code: --------------------------------------------------------------------- /* if construct, near obvious cse */ int a(int c, int a, int b, int o) { int r; if (c) { r = a - b; } else { r = a + o - b; } return r; } /* if construct, absolute obvious cse */ int b(int c, int a, int b, int o) { int r; if (c) { r = a - b; } else { r = a - b + o; } return r; } /* conditional assignment, near obvious cse */ int c(int c, int a, int b, int o) { int r; r = (c) ? a - b : a + o - b; return r; } /* conditional assignment, absolute obvious cse */ int d(int c, int a, int b, int o) { int r; r = (c) ? a - b : a - b + o; return r; } ---------------------------------------------------------------------
The "near obvious cse" cases are not obvious (requires reassociation). To make them redundant, you need code hoisting.
b and d are fixed on trunk (GCC 7) but we're just lucky with the association.
For i686 (-m32), GCC does cmov for all functions since GCC 8.1.0; with GCC 10+ having the best code gen so far (there is another bug report about improving similar functions already). For x86_64, GCC does cmov for all functions since GCC 4.6.0
a, c is really just another case of PR 64700. b and d are already optimized on the gimple level by PRE to: ``` _10 = a_4(D) - b_5(D); if (c_3(D) != 0) goto <bb 4>; [50.00%] else goto <bb 3>; [50.00%] <bb 3> [local count: 536870913]: r_7 = o_6(D) + _10; <bb 4> [local count: 1073741824]: # r_2 = PHI <_10(2), r_7(3)> ```