Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
Welcome to the Intel Community. If you get an answer you like, please mark it as an Accepted Solution to help others. Thank you!
26729 Discussions

BUG: comparing INT*2PARAMETER with INT*4. X8000 - porting OpenVMS to iFORT

JP_SECTOR7_COM
New Contributor I
305 Views

We came across the following difference between OpenVMS FORTRAN and Ifort which seem like an ifort compiler bug.

Our Fortran Porting Tool detects and fixes occurrences - but - wanted to share.

I understand that the new fortran spec insists on INT('8000'X,2) = but - if this is a problem the ifort compiler should really "say" something.

PROGRAM rick
INTEGER*2 Int2
INTEGER*2 undef_i2ko
INTEGER*4 Int4
PARAMETER (undef_i2ko = '8000'X) ! DOESNT WORK
!PARAMETER (undef_i2ko = -32768) WORKS
!PARAMETER (undef_i2ko = INT('8000'X,2)) WORKS
Int2 = undef_i2ko
Int4 = Int2
write (*,'(" undef_i2ko : ",1Z4.4,I10)') undef_i2ko, undef_i2ko
write (*,'(" Int2 : ",1Z4.4,I10)') Int2, Int2
write (*,'(" Int4 : ",1Z8.8, I10)') Int4, Int4
! ===========================================================
! seem to substitute X8000 for undef_i2ko and not sign extend
! ===========================================================
IF (Int4 .NE. undef_i2ko) THEN
WRITE(*,*)' IF (Int4 .NE. undef_i2ko) Should not happen'
ELSE
WRITE(*,*)'seems ok'
ENDIF
END

iFORT:
undef_i2ko : 8000 -32768
Int2 : 8000 -32768
Int4 : FFFF8000 -32768
IF (Int4 .NE. undef_i2ko) Should not happen

 

VMS
undef_i2ko : 8000 -32768
XInt2 : 8000 -32768
XInt4 : FFFF8000 -32768
seems ok

 

1 Solution
Steve_Lionel
Black Belt Retired Employee
245 Views

There is indeed a bug here. The IF is comparing an INTEGER(4) with an INTEGER(2). The standard says:

In the numeric relational operation
 x1 rel-op x2
 if the types or kind type parameters of x1 and x2 differ, their values are converted to the type and kind type parameter of the expression x1 + x2 before evaluation.

(You'd then need to find that rule that basically says convert to the kind with the higher range - INTEGER(4) in this case.)

But if I look at the (x86) assembly code for the comparison, I see this:

 

 

;;; ! ===========================================================
;;; ! seem to substitute X8000 for undef_i2ko and not sign extend
;;; ! ===========================================================
;;; IF (Int4 .NE. undef_i2ko) THEN

  0019f 8b 45 fc         mov eax, DWORD PTR [-4+ebp]            
$LN112:
  001a2 3d 00 80 00 00   cmp eax, 32768                         
$LN113:
  001a7 74 4f            je .B1.10 ; Prob 50%                   
$LN114:

 

 

It's easier to see what's going wrong when you view this in the debugger, but I can't copy from there. The comment has it right - the cmp instruction is comparing the value Z'FFFF8000' from Int4  with the constant Z'00008000' - these are not equal. The compiler is failing to promote the INTEGER(2) named constant to INTEGER(4), as the standard says it must.

Now, I agree that this program is VERY non-standard, but I firmly believe that this is a bug and should be reported through the Online Service Center.

View solution in original post

11 Replies
andrew_4619
Honored Contributor I
296 Views

ifort /stand test.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.1 Build 20201112_000000
Copyright (C) 1985-2020 Intel Corporation. All rights reserved.

test.f90(5): warning #6924: Fortran 2018 does not allow this constant. ['8000'X]
PARAMETER (undef_i2ko = '8000'X) ! DOESNT WORK
------------------------^
test.f90(2): warning #6916: Fortran 2018 does not allow this length specification. [2]
INTEGER*2 Int2
--------^
test.f90(3): warning #6916: Fortran 2018 does not allow this length specification. [2]
INTEGER*2 undef_i2ko
--------^
test.f90(4): warning #6916: Fortran 2018 does not allow this length specification. [4]
INTEGER*4 Int4
--------^
Microsoft (R) Incremental Linker Version 14.16.27039.0
Copyright (C) Microsoft Corporation. All rights reserved.

-out:test.exe
-subsystem:console
test.obj

 

You are expecting non-standard Fortran from one compiler  to behave in the same non-standard way in another compiler.

 

JP_SECTOR7_COM
New Contributor I
294 Views
Opps - pasted wring version   
 
PROGRAM rick
         INTEGER*2 Int2
         INTEGER*2 undef_i2ko
         INTEGER*4 Int4
         PARAMETER (undef_i2ko = '8000'X) ! DOESNT WORK
         !PARAMETER (undef_i2ko = -32768) WORKS
         !PARAMETER (undef_i2ko = INT('8000'X,2))   WORKS
         Int2 = undef_i2ko
         Int4 = Int2
         write (*,'(" undef_i2ko : ",1Z4.4,I10)') undef_i2ko, undef_i2ko
         write (*,'(" Int2 : ",1Z4.4,I10)') Int2, Int2
         write (*,'(" Int4 : ",1Z8.8, I10)') Int4, Int4
! ===========================================================
! seem to substitute X8000 for undef_i2ko and not sign extend
! ===========================================================
         IF (Int4 .NE. undef_i2ko) THEN
          WRITE(*,*)' IF (Int4 .NE. undef_i2ko) Should not happen'
        ELSE
          WRITE(*,*)'seems ok'
        ENDIF
       END
andrew_4619
Honored Contributor I
293 Views
PROGRAM rick
    INTEGER(2) :: Int2
    INTEGER(2), parameter :: undef_i2ko = int(z'8000', 2)
    INTEGER(4) :: Int4
    Int2 = undef_i2ko
    Int4 = Int2
    write (*,'(" undef_i2ko : ",1Z4.4,I10)') undef_i2ko, undef_i2ko
    write (*,'(" Int2 : ",1Z4.4,I10)') Int2, Int2
    write (*,'(" Int4 : ",1Z8.8, I10)') Int4, Int4
    ! ===========================================================
    ! seem to substitute X8000 for undef_i2ko and not sign extend
    ! ===========================================================
    IF (Int4 .NE. undef_i2ko) THEN
       WRITE(*,*)' IF (Int4 .NE. undef_i2ko) Should not happen'
    ELSE
       WRITE(*,*)'seems ok'
    ENDIF
END
C:\Users\cadfi\OneDrive\Desktop\zzz>ifort /stand test.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.1 Build 20201112_000000
Copyright (C) 1985-2020 Intel Corporation.  All rights reserved.

Microsoft (R) Incremental Linker Version 14.16.27039.0
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:test.exe
-subsystem:console
test.obj

C:\Users\cadfi\OneDrive\Desktop\zzz>test
 undef_i2ko : 8000    -32768
 Int2 : 8000    -32768
 Int4 : FFFF8000    -32768
 seems ok
JP_SECTOR7_COM
New Contributor I
289 Views
yes - as I put in the program - setting undef_i2ko to -32768 or INT('8000'x,2) both work.

the interesting point is that printing int2, in4, undef_i2ko ALL print as -32768 SO - WHY is the comparison failing ??
JP_SECTOR7_COM
New Contributor I
292 Views
JP_SECTOR7_COM
New Contributor I
292 Views
No - expecting it to sign extend the hex constant - OR - emit an error message .. actually really expecting the '8000'X to be assigned to undef_i2ko as a normal variable and have the sign extension taken care of.
andrew_4619
Honored Contributor I
288 Views

it is not standard fortran in fixed or free format.  '8000'X is not valid Fortran it is a not standard language extension.  Compile with /stand option. The example I showed is standard and works.

andrew_4619
Honored Contributor I
279 Views

a 4 byte integer can't be bitwise identical to a 2 byte integer, they have a different number of bits. 

JP_SECTOR7_COM
New Contributor I
261 Views
The bug is NOT doing bitwise compare - it's a sign entension bug.

if undek_i2ko == -32768 and int4 == -32768 they should be exactly the same, regardless of the # of bits.

otherwise you would have to program every "compare" to compare against variables of exactly the same bit width.



andrew_4619
Honored Contributor I
252 Views

int(z'8000',2) = -32768

int(z'8000',4) = 32768 

They are not the same 

 

Steve_Lionel
Black Belt Retired Employee
246 Views

There is indeed a bug here. The IF is comparing an INTEGER(4) with an INTEGER(2). The standard says:

In the numeric relational operation
 x1 rel-op x2
 if the types or kind type parameters of x1 and x2 differ, their values are converted to the type and kind type parameter of the expression x1 + x2 before evaluation.

(You'd then need to find that rule that basically says convert to the kind with the higher range - INTEGER(4) in this case.)

But if I look at the (x86) assembly code for the comparison, I see this:

 

 

;;; ! ===========================================================
;;; ! seem to substitute X8000 for undef_i2ko and not sign extend
;;; ! ===========================================================
;;; IF (Int4 .NE. undef_i2ko) THEN

  0019f 8b 45 fc         mov eax, DWORD PTR [-4+ebp]            
$LN112:
  001a2 3d 00 80 00 00   cmp eax, 32768                         
$LN113:
  001a7 74 4f            je .B1.10 ; Prob 50%                   
$LN114:

 

 

It's easier to see what's going wrong when you view this in the debugger, but I can't copy from there. The comment has it right - the cmp instruction is comparing the value Z'FFFF8000' from Int4  with the constant Z'00008000' - these are not equal. The compiler is failing to promote the INTEGER(2) named constant to INTEGER(4), as the standard says it must.

Now, I agree that this program is VERY non-standard, but I firmly believe that this is a bug and should be reported through the Online Service Center.

View solution in original post

Reply