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