Bug 27313 - Does not emit conditional moves for stores
Summary: Does not emit conditional moves for stores
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.2.0
: P3 enhancement
Target Milestone: 4.3.0
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks: spec
  Show dependency treegraph
 
Reported: 2006-04-25 15:46 UTC by Dwarak Rajagopal
Modified: 2009-05-09 12:59 UTC (History)
7 users (show)

See Also:
Host: x86_64
Target: x86_64
Build: x86_64
Known to work:
Known to fail:
Last reconfirmed: 2006-04-25 17:38:13


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Dwarak Rajagopal 2006-04-25 15:46:39 UTC
int cmov(int* A ,int B ,int C ,int* D ,int* E ,int F ,int g) {
  int k,f;
  for (k = 1; k <= 1000; k++) {
    A[k] = B+C;
    g = D[k-1] + E[k-1];
    if (g > A[k])  A[k]=g; 	/* This is not converted to cmov*/
    f += g;
  }
  return f;
}

In the above code, the if-then statement is not converted to conditional move. It fails for "noce_mem_write_may_trap_or_fault_p ()" condition in "ifcvt.c" as it thinks that there is a chance for A[k] access to trap.
The fact here is that in this case, A[k] will never trap because the A[k] is already been written once along the path from Entry to the "A[k] = g". So it is safe to convert it to a cmov statement. Though there might be two extra moves (mem to reg and vice versa) statement, it is still better to avoid the branch especially if it is unpredictable data like for the eg above.

There is a typical case like this in Spec 2006 456.hmmer benchmark. Using contional moves will make the code faster by 13%-17%. 

-Dwarak
Comment 1 Andrew Pinski 2006-04-25 17:38:13 UTC
Confirmed, if cvt should have a way to track if a memory write has happened.
Comment 2 Andrew Pinski 2006-04-25 18:38:18 UTC
The other way of getting this is to have the code converted so there is only one store instead of two:

int cmov(int* A ,int B ,int C ,int* D ,int* E ,int F ,int g) {
  int k,f;
  for (k = 1; k <= 1000; k++) {
    int t = B+C;
    g = D[k-1] + E[k-1];
    if (g > t)  t=g;      /* This is not converted to cmov*/
    A[K] = t;
    f += g;
  }
  return f;
}
Which is most likely better anyways as one it is smaller.
Comment 3 Dwarak Rajagopal 2006-04-25 19:07:53 UTC
Yes this is true. The example I posted was a simplest case where it fails.
Below mmight be a typical case where you have to do two stores. 
int cmov(int* A ,int B ,int C ,int* D ,int* E ,int F ,int g) {
  int k,f;
  for (k = 1; k <= 1000; k++) {
    A[k] = B+C;
    D[k] = C; /* D[k] may alias with A[k] */ 
    g = D[k-1] + E[k-1];
    if (g > A[k])  A[k]=g;      /* This is not converted to cmov*/
    f += g;
  }
  return f;
}

In this case, you cannot reduce the number of stores (becasue D[k] may alias with A[k]) but you still want the if conversion to take place. I think it is good to have a mechanism to track if a memory is already been written in ifcvt. I'm not sure how it can be done at this level though.  

-Dwarak


(In reply to comment #2)
> The other way of getting this is to have the code converted so there is only
> one store instead of two:
> 
> int cmov(int* A ,int B ,int C ,int* D ,int* E ,int F ,int g) {
>   int k,f;
>   for (k = 1; k <= 1000; k++) {
>     int t = B+C;
>     g = D[k-1] + E[k-1];
>     if (g > t)  t=g;      /* This is not converted to cmov*/
>     A[K] = t;
>     f += g;
>   }
>   return f;
> }
> Which is most likely better anyways as one it is smaller.
> 

Comment 4 Richard Biener 2006-09-21 13:07:32 UTC
We have a flag (TREE_THIS_NOTRAP) to annotate ARRAY_REFs and INDIRECT_REFs.  It could be used to guide tree-ifcvt to do the transformation.  Can we have if-converted stores at the tree level at all?
Comment 5 Steven Bosscher 2006-11-11 16:46:53 UTC
You can't have if-converted stores at the tree level.

Forms of store motion, like the example of comment #2, ought to get implemented at the tree level somewhen, though.  AFAIU this is currently very hard to do, but the mem-ssa and new VN projects should help simplifying the job.
Comment 6 Jim Wilson 2009-05-09 01:21:46 UTC
It looks like this was fixed by Michael Matz here:
http://gcc.gnu.org/ml/gcc-patches/2007-08/msg01978.html

This patch was added to gcc-4.3, and the gcc-4.2 branch is closed, so I think this bug should be closed resolved.
Comment 7 Richard Biener 2009-05-09 12:59:56 UTC
Fixed.