Using the code attached: >gfortran --version | head -2 GNU Fortran (GCC) 4.7.1 Copyright (C) 2012 Free Software Foundation, Inc. >gfortran -O0 -fcheck=bounds xxx_1.f xxx_2.f >/a.out 2 1 3 2 T >gfortran -O2 -fcheck=bounds xxx_1.f xxx_2.f >./a.out 2 1 3 1 F The results are different and incorrect when compiling with "-O2 -fcheck=bounds". They are still correct when compiling with "-O1 -fcheck=bounds".
Created attachment 28313 [details] test case
This seems to be a 4.7/4.8 regression. Compiling the test with ' -Wall -Wextra -Wuninitialized -O3 -fbounds-check' gives the expected results for 4.4.6, 4.5.3, and 4.6.3, but not for 4.7.2 or trunk. Revision 176696 (2011-07-23) is OK, but not revision 177649 (2011-08-11). If I initialize iaii as iaii=huge(0), I get the expected result. Note to be pedantic, the use of INTENT in the subroutine requires an interface (but it does not change anything either to add the interface or to remove the intent).
Confirmed. For the failure, it is sufficient to use: gfortran -fcheck=bounds -O1 -fstrict-overflow -ftree-pre -ftree-vrp xxx_2.f (xxx_1.f can be compiled with any option.)
Here is a reduced test case, which shows the same behavior: SUBROUTINE XXX (IL, IU) implicit none integer, INTENT(IN) :: IL, IU integer :: NXX (3) = (/ 0, 1, 2 /) integer :: ivvv, ia, iyyye, ja, iaii logical :: qop, qvv IYYYE=-1 QOP=.FALSE. DO IA=IL,IU JA=NXX(IA) QVV=JA.GT.0 IF (.NOT. QOP .and. QVV) THEN IAII=IA ivvv=1 QOP=.TRUE. ENDIF IF (QOP) THEN IF (QVV) THEN ivvv=IA-IAII+1 ! mis-compiled write(*,*) ia,ivvv ELSE IF (IA+IYYYE<1) THEN QOP=.FALSE. IYYYE=0 ENDIF ENDIF ENDDO write(*,*) ivvv==2 END subroutine program p implicit none CALL XXX (1, 3) end
Workaround: -fno-tree-vrp
It is caused by revision 176918: http://gcc.gnu.org/ml/gcc-cvs/2011-07/msg01186.html
Yeah, indeed. The bug seems to be in the second vrp pass on xxx function. iaii_23: [_79, _79] EQUIVALENCES: { } (0 elements) looks wrong (iaii_23 is only conditionally equal to _79 (in the first iteration that sets iaii, i.e. ia = 2, second iteration), it can be the value from previous cycle too (in the ia = 3, third iteration). This then leads to _35 = prephitmp_50 - iaii_23; being _35: [0, 0] (again, wrong) and that is why we end up with 1 instead of 2 in the second row. There is: Visiting PHI node: iaii_23 = PHI <iaii_1(11), prephitmp_50(10)> Argument #0 (11 -> 12 not executable) Argument #1 (10 -> 12 executable) prephitmp_50 Value: [_79, _79] EQUIVALENCES: { _79 } (1 elements) Found new range for iaii_23: [_79, _79] which is wrong, but not sure if this is the first spot in the dump. iaii_1 here is only conditionally UNDEFINED, it might be iaii value from previous iteration too.
I don't see anything wrong by what VRP does: Visiting statement: prephitmp_2 = _79; Found new range for prephitmp_2: [_79, _79] Simulating statement (from ssa_edges): iaii_23 = PHI <iaii_1(11), prephitmp_2(10)> Visiting PHI node: iaii_23 = PHI <iaii_1(11), prephitmp_2(10)> Argument #0 (11 -> 12 executable) iaii_1 Value: [_79, _79] Argument #1 (10 -> 12 executable) prephitmp_2 Value: [_79, _79] EQUIVALENCES: { _79 } (1 elements) Meeting [_79, _79] and [_79, _79] EQUIVALENCES: { _79 } (1 elements) to [_79, _79] Found new range for iaii_23: [_79, _79] Simulating statement (from ssa_edges): _35 = prephitmp_2 - iaii_23; Visiting statement: _35 = prephitmp_2 - iaii_23; Found new range for _35: [0, 0] Visiting statement: ivvv.5_36 = _35 + 1; Found new range for ivvv.5_36: [1, 1] Now changed behavior is from: Visiting PHI node: iaii_1 = PHI <iaii_18(D)(4), iaii_48(17)> Argument #0 (4 -> 5 executable) iaii_18(D) Value: UNDEFINED Argument #1 (17 -> 5 executable) iaii_48 Value: [_79, _79] Meeting UNDEFINED and [_79, _79] to [_79, _79] Found new range for iaii_1: [_79, _79] and this is all in a cycle. I think this may be mixing _79 from different iterations. Reduced testcase, maybe easier to look at: SUBROUTINE XXX (IL, IU) implicit none integer, INTENT(IN) :: IL, IU integer :: NXX (3) = (/ 0, 1, 2 /) integer :: ivvv, ia, ja, iaii logical :: qop QOP=.FALSE. DO IA=IL,IU JA=NXX(IA) IF (.NOT. QOP .and. JA.GT.0) THEN IAII=IA QOP=.TRUE. ENDIF IF (QOP) THEN ivvv=IA-IAII+1 ! mis-compiled ENDIF ENDDO IF (ivvv.NE.2) THEN call abort ENDIF END subroutine program p implicit none CALL XXX (1, 3) end
Exactly the same issue as PR53465, just instead of an equivalence we have a symbolic range [_79, _79] which is of course also an "equivalence". Trunk fails for the reduced testcase if you enlarge the array: integer :: NXX (14) = (/ 0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14 /) otherwise the loop is unrolled.
Struggling to build a C testcase with the bounds checking made explicit.
Author: rguenth Date: Wed Jan 16 13:57:48 2013 New Revision: 195238 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=195238 Log: 2013-01-16 Richard Biener <rguenther@suse.de> PR tree-optimization/54767 PR tree-optimization/53465 * tree-vrp.c (vrp_meet_1): Revert original fix for PR53465. (vrp_visit_phi_node): For PHI arguments coming via backedges drop all symbolical range information. (execute_vrp): Compute backedges. * gfortran.fortran-torture/execute/pr54767.f90: New testcase. Added: trunk/gcc/testsuite/gfortran.fortran-torture/execute/pr54767.f90 Modified: trunk/gcc/ChangeLog trunk/gcc/testsuite/ChangeLog trunk/gcc/tree-vrp.c
Fixed on trunk sofar.
Author: rguenth Date: Tue Feb 5 12:54:12 2013 New Revision: 195754 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=195754 Log: 2013-02-05 Richard Biener <rguenther@suse.de> PR tree-optimization/54767 * tree-vrp.c (vrp_visit_phi_node): For PHI arguments coming via backedges drop all symbolical range information. (execute_vrp): Compute backedges. * gfortran.fortran-torture/execute/pr54767.f90: New testcase. Added: branches/gcc-4_7-branch/gcc/testsuite/gfortran.fortran-torture/execute/pr54767.f90 Modified: branches/gcc-4_7-branch/gcc/ChangeLog branches/gcc-4_7-branch/gcc/testsuite/ChangeLog branches/gcc-4_7-branch/gcc/tree-vrp.c
Fixed.