Here is another instance of an optimization bug. This one occurs when array sections are copied and /opt /64 has been requested. The bug is rather fragile, and minor changes to the code make it disappear. To make the bug easy to notice, I made two copies of a single subroutine, which modifies an input 2-D array. The two copies are identical except for one line. The first version has, on line 64,
v (:mp1, j) = v (:mp1, jcol) ! array section copy
The second version has, instead, a DO loop, on lines 91-93:
Do k = 1, mp1; v (k, j) = v (k, jcol); End Do
The main program compares the returned arrays v from the two versions. In the absence of bugs, the two should be identical. With 32-bit compilations, or with /64 but not /opt, they are identical. With /64 /opt, the bug surfaces.
The source code:
Program tst
Implicit None
Integer :: m = 306, nvar = 4, n = 5, ns = 2
Double Precision :: eq (4, 5)
Double Precision, Dimension (307, 6) :: v, v1, v2
Integer :: i, j
Data eq/0.d0,1.d0,3*0.d0,1.d0,3*0.d0,1.d0,2*0.d0,1.d0,3*0.d0, &
1.d0,3.d0,2*0.d0/
!
do i = 1, 307
do j = 1,6
v(i, j) = i*(3.d0-j)
end do
end do
!
v1 = v
Call scrch1 (m, nvar, eq, v1)! Uses vector assignment, v (:mp1, j) = v (:mp1, jcol)
!
v2 = v
Call scrch2 (m, nvar, eq, v2)! Uses DO loop, DO k=1, mp1; v(k, j) = v(k, jcol)
!
! Check that the two results match, as they should
!
If (any(Abs(v1-v2) > 1d-6)) Then
Write (*, 10) m, nvar, n, ns
Write (*,*) 'SCRCH, diffs found'
Do i = 1, 307
Do j = 1, 6
If (Abs(v1(i, j)-v2(i, j)) > 1d-5) &
& write (*, 20) i, j,v1 (i, j), v2 (i, j)
End Do
End Do
Else
Write (*,*) 'SCRCH, no diffs'
End If
Stop
!
10 Format ('m, nvar, meqa, n, ns = ', 5 I5)
20 Format (2 I4, 2 x, 2 ES15.7)
!
End Program
!
Subroutine scrch1 (m, nvar, eq, v)
Implicit None
Integer, Intent (In) :: m, nvar
Integer :: nscol (2) = (/ 2, 3 /), iresl (4) = (/ 1, 4, 2, 1 /)
Double Precision, Intent (In) :: eq (4, 5)
Double Precision, Dimension (307, 6), Intent (Inout) :: v
Integer :: l, j, lrow, lcol, jcol, n, np1, mp1, ns
Double Precision :: fact
n = nvar + 1; np1 = n + 1; mp1 = m + 1; ns = nvar - 2
!
Do l = 1, 2
lrow = iresl (2*l-1); lcol = iresl (2*l)
Do j = 1, ns
jcol = nscol (j); fact = eq (lrow, jcol)
v (:mp1, jcol) = v (:mp1, jcol) - fact * v (:mp1, lcol)
End Do
fact = eq (lrow, n)
v (:mp1, np1) = v (:mp1, np1) - fact * v (:mp1, lcol)
End Do
Do j = 1, ns
jcol = nscol (j); If (jcol == j) Cycle
v (:mp1, j) = v (:mp1, jcol) ! array section copy
End Do
v (:mp1, n-2) = v (:mp1, n); v (:mp1, n-1) = v (:mp1, np1)
Return
End Subroutine scrch1
NOTE: The second version of the subroutine is posted in a follow-on posting below, because of the forum line limits.