Bug 29144 - Missing if-conversion. If-conversion dependent on operand order. Inconsistent if-conversion.
Summary: Missing if-conversion. If-conversion dependent on operand order. Inconsistent...
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: rtl-optimization (show other bugs)
Version: 3.4.5
: P3 enhancement
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: missed-optimization
Depends on: 64700 23286
Blocks: cmov
  Show dependency treegraph
 
Reported: 2006-09-19 15:51 UTC by Håkon Bugge
Modified: 2023-12-28 00:04 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work: 10.1.0, 8.1.0
Known to fail:
Last reconfirmed: 2009-02-06 20:58:37


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Håkon Bugge 2006-09-19 15:51:06 UTC
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;
}
---------------------------------------------------------------------
Comment 1 Steven Bosscher 2009-02-06 20:58:37 UTC
The "near obvious cse" cases are not obvious (requires reassociation). To make them redundant, you need code hoisting.
Comment 2 Richard Biener 2016-07-12 13:57:42 UTC
b and d are fixed on trunk (GCC 7) but we're just lucky with the association.
Comment 3 Andrew Pinski 2021-08-18 21:35:33 UTC
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
Comment 4 Andrew Pinski 2023-06-02 06:04:41 UTC
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)>
```