An interesting difference between compilers

Hi all,

recently I’ve submitted some simple fixes to one Fortran project and noticed a difference in results if the project compiled with different compilers.
After some more checks it became clear that there are two group of compilers with different behaviour.
“A” GNU,Intel/InteLLVM,lfortran,NAG,IBM. (expected results)
“B” AOCC, NVidia, ARM. (problematic results)

In the end the main author of the code has created a reproducer of the problem and I’ve stripped it to the following code.

program aocc_run_test
  implicit none
  real :: arr_in1(0:10, 2:5), arr1(0:10,2:5)
  real :: arr_in2(0:10, 2:5), arr2(0:10,2:5)
  real :: arr_in3(0:10, 2:5), arr3(0:10,2:5)
  integer  i, j
  do i=0,10 
  do j=2,5
    arr_in1(i,j) = 1000*i+j
    arr_in2(i,j) = 1000*i+j
    arr_in3(i,j) = 1000*i+j
  end do
  end do

  call evaluate(arr_in1,arr_in2,arr_in3,arr1,arr2,arr3)
contains

  function justcopy(arr_in) 
   real, intent(in) :: arr_in(0:,:)
   real :: justcopy(0:ubound(arr_in,dim=1), 2:5)  !This works for "A" GNU,Intel/InteLLVM,lfortran,NAG,IBM. Does not work for "B" AOCC, NVidia, ARM.
!   real :: justcopy(0:size(arr_in,dim=1)-1, 2:5) !This works for all compilers
   write(*,*)lbound(arr_in,dim=1),ubound(arr_in,dim=1),size(arr_in,1)
   write(*,*)lbound(arr_in,dim=2),ubound(arr_in,dim=2),size(arr_in,2)
   write(*,*)lbound(justcopy,dim=1),ubound(justcopy,dim=1),size(justcopy,1)
   justcopy=arr_in
   write(*,*)lbound(justcopy,dim=1),ubound(justcopy,dim=1),size(justcopy,1)
  end function justcopy
  
  subroutine evaluate(arr_in1,arr_in2,arr_in3,arr_out1,arr_out2,arr_out3)
    real,    intent(in)  :: arr_in1(:,:)
    real,    intent(in)  :: arr_in2(:,:)
    real,    intent(in)  :: arr_in3(:,:)
    real,    intent(out) :: arr_out1(:,:)
    real,    intent(out) :: arr_out2(:,:)
    real,    intent(out) :: arr_out3(:,:)
    real, allocatable  :: X(:,:)

    arr_out1 = justcopy(arr_in1)
    X = justcopy(arr_in2)       
    arr_out2 = X
    arr_out3 = 1.0*justcopy(arr_in3)

    write(*,*)"X--       ", lbound(X), ubound(X),size(X,1) !This line is different for "A" and "B" compilers with "ubound"
    write(*,*)X
    write(*,*)"arr_out1--", lbound(arr_out1), ubound(arr_out1),size(arr_out1,1)
    write(*,*)arr_out1
    write(*,*)"arr_out2--", lbound(arr_out2), ubound(arr_out2),size(arr_out2,1)
    write(*,*)arr_out2
    write(*,*)"arr_out3--", lbound(arr_out3), ubound(arr_out3),size(arr_out3,1)
    write(*,*)arr_out3
    !With ubound arr_out3=arr_out2 != arr_out1 != X
  end subroutine evaluate  
end program aocc_run_test

It seems the main difference is the way the specification part of the code work. I have looked into the 7.1.11 of https://j3-fortran.org/doc/year/10/10-007r1.pdf and my reading is that the code with ubound should work, as ubound is allowed in the specification. But I’m not sure and would appreciate hearing your opinion on this.

Best regards,

Andrii

1 Like

It might help us if you’ll say what the expected and unexpected results are. I don’t have access to any of the group B compilers.

Dear @sblionel,

please see the results attached.

The bad case works as if the ubound(arr_in)is evaluated first and only then the lower boundary of arr_in is set to 0.

Best regards,

Andrii

good

           0          10          11
           1           4           4
           0          10          11
           0          10          11
           0          10          11
           1           4           4
           0          10          11
           0          10          11
           0          10          11
           1           4           4
           0          10          11
           0          10          11
 X--                  1           1          11           4          11
   2.00000000       1002.00000       2002.00000       3002.00000       4002.00000       5002.00000       6002.00000       7002.00000       8002.00000       9002.00000       10002.0000       3.00000000       1003.00000       2003.00000       3003.00000       4003.00000       5003.00000       6003.00000       7003.00000       8003.00000       9003.00000       10003.0000       4.00000000       1004.00000       2004.00000       3004.00000       4004.00000       5004.00000       6004.00000       7004.00000       8004.00000       9004.00000       10004.0000       5.00000000       1005.00000       2005.00000       3005.00000       4005.00000       5005.00000       6005.00000       7005.00000       8005.00000       9005.00000       10005.0000    
 arr_out1--           1           1          11           4          11
   2.00000000       1002.00000       2002.00000       3002.00000       4002.00000       5002.00000       6002.00000       7002.00000       8002.00000       9002.00000       10002.0000       3.00000000       1003.00000       2003.00000       3003.00000       4003.00000       5003.00000       6003.00000       7003.00000       8003.00000       9003.00000       10003.0000       4.00000000       1004.00000       2004.00000       3004.00000       4004.00000       5004.00000       6004.00000       7004.00000       8004.00000       9004.00000       10004.0000       5.00000000       1005.00000       2005.00000       3005.00000       4005.00000       5005.00000       6005.00000       7005.00000       8005.00000       9005.00000       10005.0000    
 arr_out2--           1           1          11           4          11
   2.00000000       1002.00000       2002.00000       3002.00000       4002.00000       5002.00000       6002.00000       7002.00000       8002.00000       9002.00000       10002.0000       3.00000000       1003.00000       2003.00000       3003.00000       4003.00000       5003.00000       6003.00000       7003.00000       8003.00000       9003.00000       10003.0000       4.00000000       1004.00000       2004.00000       3004.00000       4004.00000       5004.00000       6004.00000       7004.00000       8004.00000       9004.00000       10004.0000       5.00000000       1005.00000       2005.00000       3005.00000       4005.00000       5005.00000       6005.00000       7005.00000       8005.00000       9005.00000       10005.0000    
 arr_out3--           1           1          11           4          11
   2.00000000       1002.00000       2002.00000       3002.00000       4002.00000       5002.00000       6002.00000       7002.00000       8002.00000       9002.00000       10002.0000       3.00000000       1003.00000       2003.00000       3003.00000       4003.00000       5003.00000       6003.00000       7003.00000       8003.00000       9003.00000       10003.0000       4.00000000       1004.00000       2004.00000       3004.00000       4004.00000       5004.00000       6004.00000       7004.00000       8004.00000       9004.00000       10004.0000       5.00000000       1005.00000       2005.00000       3005.00000       4005.00000       5005.00000       6005.00000       7005.00000       8005.00000       9005.00000       10005.0000    

bad

            0           10           11
            1            4            4
            0           10           11
            0           10           11
            0           10           11
            1            4            4
            0           10           11
            0           10           11
            0           10           11
            1            4            4
            0           10           11
            0           10           11
 X--                   0            2           11            5           12
    2.000000        1002.000        2002.000        3002.000     
    4002.000        5002.000        6002.000        7002.000     
    8002.000        9002.000        10002.00        3.000000     
    1003.000        2003.000        3003.000        4003.000     
    5003.000        6003.000        7003.000        8003.000     
    9003.000        10003.00        4.000000        1004.000     
    2004.000        3004.000        4004.000        5004.000     
    6004.000        7004.000        8004.000        9004.000     
    10004.00        5.000000        1005.000        2005.000     
    3005.000        4005.000        5005.000        6005.000     
    7005.000        8005.000        9005.000        10005.00     
    0.000000        0.000000        0.000000        0.000000    
 arr_out1--            1            1           11            4           11
    2.000000        1002.000        2002.000        3002.000     
    4002.000        5002.000        6002.000        7002.000     
    8002.000        9002.000        10002.00        3.000000     
    1003.000        2003.000        3003.000        4003.000     
    5003.000        6003.000        7003.000        8003.000     
    9003.000        10003.00        4.000000        1004.000     
    2004.000        3004.000        4004.000        5004.000     
    6004.000        7004.000        8004.000        9004.000     
    10004.00        5.000000        1005.000        2005.000     
    3005.000        4005.000        5005.000        6005.000     
    7005.000        8005.000        9005.000        10005.00    
 arr_out2--            1            1           11            4           11
    2.000000        1002.000        2002.000        3002.000     
    4002.000        5002.000        6002.000        7002.000     
    8002.000        9002.000        10002.00        1003.000     
    2003.000        3003.000        4003.000        5003.000     
    6003.000        7003.000        8003.000        9003.000     
    10003.00        4.000000        2004.000        3004.000     
    4004.000        5004.000        6004.000        7004.000     
    8004.000        9004.000        10004.00        5.000000     
    1005.000        3005.000        4005.000        5005.000     
    6005.000        7005.000        8005.000        9005.000     
    10005.00        0.000000        0.000000        0.000000    
 arr_out3--            1            1           11            4           11
    2.000000        1002.000        2002.000        3002.000     
    4002.000        5002.000        6002.000        7002.000     
    8002.000        9002.000        10002.00        1003.000     
    2003.000        3003.000        4003.000        5003.000     
    6003.000        7003.000        8003.000        9003.000     
    10003.00        4.000000        2004.000        3004.000     
    4004.000        5004.000        6004.000        7004.000     
    8004.000        9004.000        10004.00        5.000000     
    1005.000        3005.000        4005.000        5005.000     
    6005.000        7005.000        8005.000        9005.000     
    10005.00        0.000000        0.000000        0.000000    

Thanks for that. Group B compilers are wrong here, probably misunderstanding the rules for lbound and ubound for non-pointer dummy arguments.

2 Likes

Dear @sblionel,

thank you very much for the input. I will also try to fill some bugreports and if there will be feedback, I will post it here.

Best regards,

Andrii

1 Like

I’ve been removed from this for a while, but I think AOCC and Arm are based on Classic Flang, which was derived from the NVIDIA compiler. That could explain all the Group B behavior.

2 Likes

Yes, we have noted that the common property of the compilers in B group is LLVM backend (it seems the IBM v17 compiler belongs to the group B). But I’m still not sure, as IntelLLVM has the same backend and the genealogy of the compilers is not very clear for me – the name “flang” is used too often.

1 Like

@Andrii thanks for trying all compilers, and I am happy that LFortran worked for this, we are still in alpha, so it’s always a pleasant surprise for me when it actually works.

This bug is not due to using LLVM (LFortran also uses LLVM), but due to the front end and middle end of the compiler, which determines how these intrinsic functions l/ubound should behave and how they should be lowered to LLVM.

1 Like

flang-new/llvm-flang also produces the “good” result.

1 Like