Do IEEE modes reset automatically upon return?

This is a continuation of an interesting tangent in the Poll thread.

Here is a short program that tests whether the compiler (processor) automatically resets the underflow mode upon return from a subprogram.

program ieee
   use, intrinsic :: iso_fortran_env, wp=>real32
   use, intrinsic :: ieee_arithmetic
   implicit none
   real(wp) :: x
   if ( .not. ieee_support_underflow_control(x) ) then
      write(*,*) 'underflow control is not supported for kind(x)=', kind(x)
      stop
   endif
   write(*,*) 'underflow control is supported for kind(x)=', kind(x)
   x = tiny(x) * 1.e-5_wp
   call print_stuff('default',x)
   call toggle_mode()
   x = tiny(x) * 1.e-5_wp
   call print_stuff('first toggle',x)
   call toggle_mode()
   x = tiny(x) * 1.e-5_wp
   call print_stuff('second toggle',x)
contains
   subroutine print_stuff(title,x)
      ! print ieee info about x.
      character(*), intent(in) :: title
      real(wp), intent(in) :: x
      write(*,*) '==== ', title, ' ===='
      write(*,*) 'x=', x
      write(*,*) 'ieee_support_datatype(x)=', ieee_support_datatype(x)
      write(*,*) 'ieee_support_subnormal(x)=', ieee_support_subnormal(x)
      write(*,*) 'subnormal test =', (ieee_class(x) == ieee_positive_subnormal)
      return
   end subroutine print_stuff
   subroutine toggle_mode()
      ! toggle the underflow mode.
      logical :: gradual
      call ieee_get_underflow_mode( gradual )
      write(*,*) 'toggle: input underflow mode is ', gradual
      call ieee_set_underflow_mode( gradual = (.not. gradual) )
      call ieee_get_underflow_mode( gradual )
      write(*,*) 'toggle: new underflow mode is ', gradual
   end subroutine toggle_mode
end program ieee

$ gfortran ieee.f90 && a.out
 underflow control is supported for kind(x)=           4
 ==== default ====
 x=   1.17709071E-43
 ieee_support_datatype(x)= T
 ieee_support_subnormal(x)= T
 subnormal test = T
 toggle: input underflow mode is  T
 toggle: new underflow mode is  F
 ==== first toggle ====
 x=   0.00000000    
 ieee_support_datatype(x)= T
 ieee_support_subnormal(x)= T
 subnormal test = F
 toggle: input underflow mode is  F
 toggle: new underflow mode is  T
 ==== second toggle ====
 x=   1.17709071E-43
 ieee_support_datatype(x)= T
 ieee_support_subnormal(x)= T
 subnormal test = T

$ flang ieee.f90 && a.out
 underflow control is supported for kind(x)= 4
 ==== default ====
 x= 1.18E-43
 ieee_support_datatype(x)= T
 ieee_support_subnormal(x)= T
 subnormal test = T
 toggle: input underflow mode is  F
 toggle: new underflow mode is  F
 ==== first toggle ====
 x= 1.18E-43
 ieee_support_datatype(x)= T
 ieee_support_subnormal(x)= T
 subnormal test = T
 toggle: input underflow mode is  F
 toggle: new underflow mode is  F
 ==== second toggle ====
 x= 1.18E-43
 ieee_support_datatype(x)= T
 ieee_support_subnormal(x)= T
 subnormal test = T

$ nagfor ieee.f90 && a.out
NAG Fortran Compiler Release 7.2(Shin-Urayasu) Build 7203
[NAG Fortran Compiler normal termination]
 underflow control is supported for kind(x)= 1
 ==== default ====
 x=   1.1770907E-43
 ieee_support_datatype(x)= T
 ieee_support_subnormal(x)= T
 subnormal test = T
 toggle: input underflow mode is  T
 toggle: new underflow mode is  F
 ==== first toggle ====
 x=   1.1770907E-43
 ieee_support_datatype(x)= T
 ieee_support_subnormal(x)= T
 subnormal test = T
 toggle: input underflow mode is  T
 toggle: new underflow mode is  F
 ==== second toggle ====
 x=   1.1770907E-43
 ieee_support_datatype(x)= T
 ieee_support_subnormal(x)= T
 subnormal test = T

This is on MacOS with arm64 hardware. Gfortran behaves as I had expected. Namely, the programmer can reset the underflow mode in a subroutine, and that reset sticks after return for the rest of the program. Is this standard conforming behavior?

Flang for some reason does not allow the underflow mode to be changed, despite saying that it can be changed with the ieee_support_underflow_control(x) function. The result of ieee_get_underflow_mode() seems to be incorrect. Otherwise, the other ieee tests on the value seem to work correctly. Maybe I’m doing something wrong in the toggle_mode() subroutine? BTW, flang also prints some run time warning messages about the underflows to stderr, which I did not include in the above output.

The NAG fortran compiler does seem to reset the underflow mode upon return from toggle_mode(). If you move the ieee_set_underflow_mode() call to the main program instead of the subroutine, then the mode toggles as expected. This is the opposite of my expectations. On the downside however, when you do that the subnormal test prints T when the argument is 0.0, so I don’t think that part is right. However, I’m still unsure if I’m doing that test correctly.

FWIW, I tried your program with ifx version 2025.0.0 on Windows and got essentially the same output as you show for the NAG compiler.

1 Like

The Standard uses identical or very similar words for

  • the IEEE exceptions : If a flag is signaling on entry to a procedure other than IEEE_GET_FLAG or IEEE_GET_STATUS, the processor will set it to quiet on entry and restore it to signaling on return. If a flag signals during execution of a procedure, the processor shall not set it to quiet on return.
  • the IEEE rounding modes : In a procedure other than IEEE_SET_ROUNDING_MODE or IEEE_SET_STATUS, the processor shall not change the rounding modes on entry, and on return shall ensure that the rounding modes are the same as they were on entry.
  • the IEEE underflow mode :In a procedure other than IEEE_SET_UNDERFLOW_MODE or IEEE_SET_STATUS, the processor shall not change the underflow mode on entry, and on return shall ensure that the underflow mode is the same as it was on entry.
  • the IEEE halting mode : In a procedure other than IEEE_SET_HALTING_MODE or IEEE_SET_STATUS, the processor shall not change the halting mode on entry, and on return shall ensure that the halting mode is the same as it was on entry.
2 Likes

I must admit that when I read that text (all of the ones you quote, not just for gradual underflow), I cannot parse what it says in a unique way. Let’s focus on the underflow case since that is what I used in the above code.

The first prepositional phrase “In a procedure other than IEEE_SET_UNDERFLOW_MODE or IEEE_SET_STATUS” says that those two procedures are exempted from the restriction that follows. The restriction that follows is that the processor is not allowed to change the underflow mode, either temporarily or permanently, within any other procedure.

When I read that, I’m thinking it means that the programmer has control of the underflow mode, and that the processor (e.g. within the matmul() intrinsic procedure, or the dot_product() intrinsic procedure, or any other procedure provided by the processor) is not allowed to reset the mode, perform the operation, and then reset it back, or to reset the mode, perform the operation, and leave the mode changed from what it was on entry. I read that as a restriction on the processor, not on the programmer. I read it as the programmer is still free, through those two set routines, to change the underflow mode however he wants, either temporarily or permanently. If the programmer wants only a temporary change, then he must query the mode and save the entry value, change the mode, perform the operations within that procedure, and then restore the original mode upon return. If he wants a permanent change, then he makes it through those two special procedures, and that mode remains that way until it is changed at some later time by the programmer.

The other way to parse that sentence is that the programmer is not allowed to change the underflow mode within a subroutine, and then have that change persist past the return statement. The processor must insert whatever necessary code is required upon return to restore the underflow mode back to its original state upon entry. This interpretation of the text is similar to the state of a local allocatable entity, which is always restored to a deallocated state upon return, whether the programmer does it explicitly or the processor does it automatically.

So I guess the question in this thread is which interpretation is intended by the standard? It looks so far like gfortran is consistent with the first interpretation, and that nagfor and ifx are consistent with the second interpretation. The flang compiler does not allow the mode to be reset, so it is broken in this respect and cannot be used to support either interpretation. Has there been an official interpretation by the standard committee on this question?

@sblionel and @tmj, I believe are attending J3 tomorrow so perhaps they would be kind enough to let us know.

I view the standard’s text, as excerpted by @themos , to be clear. Changes to the various IEEE modes within a procedure are reverted on return from that procedure. The “first prepositional phrase” is simply intended to say that those two intrinsic module procedures can change the mode(s) and leave them changed upon return - otherwise there would be no point to them.

As for MATMUL, DOT_PRODUCT, etc., it seems clear to me that they are allowed to change IEEE modes as long as they revert them upon return.