http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55806
Bug #: 55806
Summary: Missed optimization with ANY or ALL
Classification: Unclassified
Product: gcc
Version: 4.8.0
Status: UNCONFIRMED
Severity: enhancement
Priority: P3
Component: fortran
AssignedTo: [email protected]
ReportedBy: [email protected]
Mike Metcalf complains (correctly) in
<[email protected]>
that using ANY as an idiom instead of .or. for a small number of conditions.
Look at this:
module mymod
contains
subroutine bar(a,b,c)
integer, dimension(3,3), intent(in) :: a,b
integer, intent(out) :: c
real, parameter :: acc = 1e-4
integer :: i
c = 0
do i=1,3
if (any([abs(a(i,1) - b(i,1)) > acc, &
abs(a(i,2) - b(i,2)) > acc, &
abs(a(i,3) - b(i,3)) > acc])) cycle
c = c + 1
end do
end subroutine bar
end module mymod
This generates a logical array, assigns the values to them,
and then loops over the array to generate the values:
atmp.1.dtype = 273;
atmp.1.dim[0].stride = 1;
atmp.1.dim[0].lbound = 0;
atmp.1.dim[0].ubound = 2;
atmp.1.data = (void * restrict) &A.2;
atmp.1.offset = 0;
(*(logical(kind=4)[3] * restrict) atmp.1.data)[0] =
(real(kind=4)) ABS_EXPR <(*a)[(integer(kind=8)) i + -1] -
(*b)[(integer(kind=8)) i + -1]> > 9.99999974737875163555145263671875e-5;
(*(logical(kind=4)[3] * restrict) atmp.1.data)[1] =
(real(kind=4)) ABS_EXPR <(*a)[(integer(kind=8)) i + 2] - (*b)[(integer(kind=8))
i + 2]> > 9.99999974737875163555145263671875e-5;
(*(logical(kind=4)[3] * restrict) atmp.1.data)[2] =
(real(kind=4)) ABS_EXPR <(*a)[(integer(kind=8)) i + 5] - (*b)[(integer(kind=8))
i + 5]> > 9.99999974737875163555145263671875e-5;
{
integer(kind=8) S.4;
S.4 = 0;
while (1)
{
if (S.4 > 2) goto L.5;
if (NON_LVALUE_EXPR <(*(logical(kind=4)[3] * restrict)
atmp.1.data)[S.4]>)
{
test.0 = 1;
goto L.4;
}
S.4 = S.4 + 1;
}
L.5:;
}
L.4:;
if (test.0) goto L.1;
}
L.3:;
*c = *c + 1;
L.1:;
D.1907 = i == 3;
i = i + 1;
if (D.1907) goto L.2;
}
The middle-end then fails to remove this array.
Compare this to the result of
module mymod
contains
subroutine bar(a,b,c)
real, dimension(3,3), intent(in) :: a,b
integer, intent(out) :: c
real, parameter :: acc = 1e-4
integer :: i
c = 0.
do i=1,3
if (abs(a(i,1) - b(i,1)) > acc .or. &
abs(a(i,2) - b(i,2)) > acc .or. &
abs(a(i,3) - b(i,3)) > acc) cycle
c = c + 1
end do
end subroutine bar
end module mymod
What the Fortran FE generates here isn't very idiomatic when you
write in a language like C. Should we tackle this in the middle
end, or would issuing the version with .or instead of the ANY
to the middle end be preferred?