Compare this:
$ cat count.f90
program main
implicit none
integer, parameter :: value = 747
integer :: p1, p2, p3, p4
integer :: i
do i=1, 10
do p1 = 1, value-2
do p2 = p1 + 1, value - p1
do p3 = p2 + 1, value - p1 - p2
p4 = value - p1 - p2 - p3
if (p1 * p2 * p3 * p4 == value * 1000000) &
print '(4(I0,:" "))',p1,p2,p3,p4
end do
end do
end do
end do
end program main
$ gfortran -O3 count.f90
$ time ./a.out > /dev/null
real 0m0.634s
user 0m0.620s
sys 0m0.004s
with the equivalent
$ cat count.c
#include <stdio.h>
const int value = 747;
int main()
{
int i, p1, p2, p3, p4;
for (i=1; i<=10; i++)
{
for (p1 = 1; p1 <= value - 2 ; p1++)
{
for (p2 = p1 + 1; p2 <= value - p1; p2++)
{
for (p3 = p2 + 1; p3 <= value - p1 - p2; p3++)
{
p4 = value - p1 - p2 - p3;
if (p1 * p2 * p3 * p4 == value * 1000000)
printf("%d %d %d %d\n", p1, p2, p3, p4);
}
}
}
}
}
$ gcc -O3 count.c
$ time ./a.out > /dev/null
real 0m0.396s
user 0m0.380s
sys 0m0.000s
We don't
- take advantage of the fact that p1, p2, p3 and p4 cannot
be legally changed in the do loop
- take advantage of the fact that the I/O statemetns don't change
the values
so we miss out on common subexpression elimination. Here's a
part from the *.optimized file:
<L34>:;
p2.3 = p2;
p3.5 = p2.3 + 1;
D.1014 = (747 - p1) - p2.3;
p3 = p3.5;
if (p3.5 <= D.1014) goto <L35>; else goto <L12>;
<L35>:;
p1.58 = p1;
p2.60 = p2;
p3.61 = p3;
p4.7 = ((747 - p1.58) - p2.60) - p3.61;
p4 = p4.7;
if (((p2.60 * p1.58) * p3.61) * p4.7 == 747000000) goto <L8>; else goto <L9>;
--
Summary: Invariant DO loop variables (and I/O)
Product: gcc
Version: 4.3.0
Status: UNCONFIRMED
Keywords: missed-optimization
Severity: enhancement
Priority: P3
Component: fortran
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: tkoenig at gcc dot gnu dot org
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31593