https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91337

            Bug ID: 91337
           Summary: gfortran skips an if statement with some mathematical
                    optimisations with complex numbers.
           Product: gcc
           Version: 9.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: fortran
          Assignee: unassigned at gcc dot gnu.org
          Reporter: chinoune.mehdi at hotmail dot com
  Target Milestone: ---

I have encountered some underflows/overflows in my code compiled with -Ofast,
and after investigations it seems like the complex abs gives zero with small
numbers. So I added a workaround. but it didn't work:

module m
  implicit none
  !
  integer, parameter :: sp = selected_real_kind(6)
  real(sp), parameter :: tiny_sp = tiny(1._sp), sqrt_tiny = sqrt( tiny_sp )
  !
contains
  subroutine sub(z,y)
    complex(sp), intent(in) :: z
    real(sp), intent(out) :: y
    real(sp) :: az
    !
    az = abs(z)
    if( az<tiny_sp ) az = abs(z/sqrt_tiny)*sqrt_tiny
    ! if( az<tiny_sp .or. az==0._sp ) az = abs(z/sqrt_tiny)*sqrt_tiny
    print*, az<tiny_sp, az
    y = 1._sp/az
    !
  end subroutine sub
end module m
!
program bug_skip_if
  use m
  implicit none
  complex(sp) :: z
  real(sp) :: y
  !
  z = (1.e-19_sp,0._sp)
  call sub(z,y)
  print*,"y = ",y
  !
end program bug_skip_if

gfortran-9 -O1 -funsafe-math-optimizations -ffinite-math-only bug_skip_if.f90
-o test.x
./test.x
 T   0.00000000
y =          Infinity

I tried to write an equivalent c code, but it gives the right result:

#include <stdio.h>
#include <float.h>
#include <math.h>
#include <complex.h>

void foo(float complex z, float *y){
    float const sqrt_flt_min = sqrtf( FLT_MIN );
    float az;
    az = cabsf(z);
    if( az<FLT_MIN ) az = cabsf(z/sqrt_flt_min) * sqrt_flt_min;
    printf("az = %.8e\n",az);
    *y = 1.f/az;
}

int main(){
    float complex z;
    float y;

    z = 1.e-19f + 0.*I;
    foo(z,&y);
    printf("y = %.7e\n",y);

    return 0;
}

gcc-9 -O1 -funsafe-math-optimizations -ffinite-math-only cbug_skip_if.c -lm -o
test.x
./test.x
az = 9.99999968e-20
y = 1.0000000e+19

Q : Why does gfortran skip the if statement?

OS : Linux Ubuntu 18.04 x86_64
Compilers : gfortran 9.1.0 and 8.3.0

Reply via email to