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
Confirmed, if cvt should have a way to track if a memory write has happened.
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.
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. >
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?
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.
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.
Fixed.