Incorrect do-loop code with high optimization

% cat bad.f90
program bad
  implicit none

  integer, parameter :: N = huge(N), M = 10

  integer :: i, j

  outer: do i = M, N
     do j = 1, M
        if (mod(i,j) /= 0) cycle outer
     end do
     exit outer
  end do outer
  print *, i
end program bad

% pgf90 -O1 -o bad bad.f90
% ./bad
         2520
% pgf90 -O2 -o bad bad.f90
% ./bad
           11
% pgf90 -V

pgf90 8.0-5 64-bit target on x86-64 Linux -tp core2-64
Copyright 1989-2000, The Portland Group, Inc.  All Rights Reserved.
Copyright 2000-2009, STMicroelectronics, Inc.  All Rights Reserved.

I suppose my value of N is somewhat sketchy to use as the upper bound of the do-loop, so this may not really be a bug, although it is a bit of a surprise. In fact, changing the value of N to huge(N) - 1 does fix the problem. Oddly enough, using modulo instead of mod also fixes the problem.

Hi rusteve,

The compiler is doing a legitimate optimization of moving the loop test to the bottom of the loop. Though, in order to do this it needs to check against the loop bound plus one, thus causing the value of N to overflow.

You could do something like the following:

% cat test.f90
program bad
  implicit none

  integer*4 :: L
  integer*8, parameter :: N = huge(L), M=10
  integer*8 :: i, j

  outer: do i = M, N
     do j = 1, M
        if (mod(i,j) /= 0) cycle outer
     end do
     exit outer
  end do outer
  print *, i
end program bad
% pgf90 -O2 test.f90
% a.out
                     2520
  • Mat