Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Bad optimized assembly code generated for Fortran

van_der_merwe__ben
New Contributor I
662 Views

When we compile the Fortran code below, we get this error in Visual Studio:

Exception thrown at 0x4B426F3 (kbcunitop.dll) in Petro-SIM.exe: 0xC000005: Access violation reading location 0xFFFFFFFF

I apologize for not being able to include a full project and all the files, but the error is very reproducible using only a small snippet of code, and centers around this snippet of code:

      integer, parameter :: UNINT     = -32767

   DO 20 I = 1 , LMIDEX
      MINDEX (I) = UNINT
   20 CONTINUE

The rest is not really relevant.

       SUBROUTINE BDINDX

      INCLUDE 'SYS_UNDEFINED.INC'
      INCLUDE 'SYS_MINDEXSIZES.INC'
      INCLUDE 'INDEXS.COM'
      INCLUDE 'SINDEX_CACHES.COM'
*
*
      INTRINSIC MIN
*
      INTEGER I,INT1,TYPEC,IOS
      CHARACTER CHAR2*20
      DOUBLE PRECISION REAL1
*
* ------------------------------------------------------------------------------
*
      LMIDEX = MMIDEX
      CALL GTCFGK ('LMIDEX',CHAR2,INT1,REAL1,TYPEC,IOS)
      IF ( IOS.EQ.0 .AND. TYPEC.EQ.2 ) THEN
         LMIDEX = MIN(INT1,LMIDEX)
      ENDIF
      
      DO 20 I = 1 , LMIDEX
         MINDEX (I) = UNINT
   20 CONTINUE
*
      MINDEX(1) = 0
      MINDEX(3) = 0
      MINDEX(4) = SIZTOP + 1
      MINDEX(7) = 0
      MINDEX(8) = 0

 

Indexs.com has:

      INTEGER MMIDEX,MSIDEX,LSIDEX,LYMSTK,LMIDEX
      PARAMETER (MMIDEX=120000,MSIDEX=6000,LYMSTK=10)
      INTEGER MINDEX(MMIDEX),SINDEX(MSIDEX),PMODEL,PSCLST,MOFFST,       &
     &        YMSTCK(3,LYMSTK),TOPYMS
      COMMON /INDEX1/ MINDEX,PMODEL,PSCLST,MOFFST,YMSTCK,TOPYMS    

The compile options are:

/fp:source

/Ox
/W1 /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /c
/nologo /warn:nofileopt /align:rec1byte
/iface:mixed_str_len_arg
/include:"c:\PROGRA~2\INTELS~1\PARALL~1.041\COMPIL~1\windows\compiler\include\ia32"
/include:"c:\PROGRA~2\INTELS~1\PARALL~1.041\COMPIL~1\windows\compiler\include"
/Fomobj32p\kbcunitop\
/module:mobj32p\kbcunitop
/include:..\FCC-SIM /include:..\Petrofine\includes /include:
/compile_only /dll /threads /assume:byterecl /libs:dll
/define:KBCIFORTRAN

The compiler is:

Intel(R) Visual Fortran Compiler for applications running on IA-32, Version 16.0.0.110 Build 20150815
Copyright (C) 1985-2015 Intel Corporation.  All rights reserved.

The assembly generated is:

_BDINDX:

04B42680  push        ebp  
04B42681  mov         ebp,esp  
04B42683  and         esp,0FFFFFFF0h  
04B42686  push        esi  
04B42687  push        edi  
04B42688  push        ebx  
04B42689  sub         esp,14h  
04B4268C  mov         dword ptr ds:[53122E0h],1D4C0h  
04B42696  lea         esi,[esp+10h]  
04B4269A  lea         ebx,[esp+0Ch]  
04B4269E  lea         edi,[esp+8]  
04B426A2  lea         eax,[esp]  
04B426A5  push        esi  
04B426A6  push        ebx  
04B426A7  push        eax  
04B426A8  push        edi  
04B426A9  push        14h  
04B426AB  push        58E4CE0h  
04B426B0  push        6  
04B426B2  push        4F08A50h  
04B426B7  call        _GTCFGK (04BF3300h)  
04B426BC  add         esp,20h  
04B426BF  cmp         dword ptr [esp+10h],0  
04B426C4  jne         _BDINDX+51h (04B426D1h)  
04B426C6  cmp         dword ptr [esp+0Ch],2  
04B426CB  je          _BDINDX+263h (04B428E3h)  
04B426D1  mov         edx,dword ptr ds:[53122E0h]  
04B426D7  test        edx,edx  
04B426D9  jle         _BDINDX+0BCh (04B4273Ch)  
04B426DB  cmp         edx,10h  
04B426DE  jl          _BDINDX+29Eh (04B4291Eh)  
04B426E4  mov         eax,edx  
04B426E6  xor         ecx,ecx  
04B426E8  movdqa      xmm0,xmmword ptr ds:[4F08A40h]  
04B426F0  and         eax,0FFFFFFF0h  
04B426F3  movdqa      xmmword ptr [ecx*4+5297198h],xmm0   CRASH LINE
04B426FC  movdqa      xmmword ptr [ecx*4+52971A8h],xmm0     
04B42705  movdqa      xmmword ptr [ecx*4+52971B8h],xmm0  
04B4270E  movdqa      xmmword ptr [ecx*4+52971C8h],xmm0  
04B42717  add         ecx,10h  
04B4271A  cmp         ecx,eax  
04B4271C  jb          _BDINDX+73h (04B426F3h)  
04B4271E  lea         ecx,[eax+1]  
04B42721  cmp         edx,ecx  
04B42723  jb          _BDINDX+0BCh (04B4273Ch)  
04B42725  sub         edx,eax  
04B42727  xor         ecx,ecx  
04B42729  shl         eax,2  
04B4272C  mov         dword ptr [eax+ecx*4+5297198h],0FFFF8001h  
04B42737  inc         ecx  
04B42738  cmp         ecx,edx  
04B4273A  jb          _BDINDX+0ACh (04B4272Ch)  
04B4273C  push        esi  
04B4273D  push        ebx  
04B4273E  xor         edx,edx  
04B42740  lea         eax,[esp+8]  
04B42744  push        eax  
04B42745  push        edi  
04B42746  push        14h  
04B42748  push        58E4CE0h  

We can work around it by creating a method that gets called that just assigns the desired value to the entire array in one go. That method CANNOT be in the same file, otherwise the compiler optimises it out and it crashes again. This crash did not manifest in earlier versions of Intel Fortran and does not manifest if compiled with the Od option.

We do have many registered Intel Fortran users, I tried to log this issue with support, but I had no luck with that web site.

Lionel, maybe you can pass this to them, please?

 

0 Kudos
8 Replies
Steven_L_Intel1
Employee
662 Views

Sorry, I can't do anything with this without a complete test case. I don't even see a declaration of MINDEX.

0 Kudos
van_der_merwe__ben
New Contributor I
662 Views

The scary thing is, I have set up a Visual Studio project, same Fortran version, same compile options, this file and the include files only. Never crashes or generates the assembly shown. I guess it shall remain a mystery.

0 Kudos
jimdempseyatthecove
Honored Contributor III
662 Views

Steve,

04B426E4  mov         eax,edx  
04B426E6  xor         ecx,ecx  
04B426E8  movdqa      xmm0,xmmword ptr ds:[4F08A40h]  
04B426F0  and         eax,0FFFFFFF0h  
04B426F3  movdqa      xmmword ptr [ecx*4+5297198h],xmm0   CRASH LINE
04B426FC  movdqa      xmmword ptr [ecx*4+52971A8h],xmm0     
04B42705  movdqa      xmmword ptr [ecx*4+52971B8h],xmm0  
04B4270E  movdqa      xmmword ptr [ecx*4+52971C8h],xmm0  
04B42717  add         ecx,10h  
04B4271A  cmp         ecx,eax  
04B4271C  jb          _BDINDX+73h (04B426F3h)  

The base of the array is at 0x5297198, this is at an odd number of multiple of 8 address. movdqa requires a multiple of 16 byte address. (ecx walks from 0, stride 10). There should have been a general protection fault not a fault reading 0xFFFFFFFF.

benifck,

Did you make any declaration as to if MINDEX were aligned? Can you provide your declaration of MINDEX including any !DEC$ decorations.

The binary code could exhibit this behavior when your COMMON or module based array did .NOT. have an alignment declaration, .AND. your subroutine has a directive (possibly implied by option) that specifies the array is aligned (and the array by chance did not fall on an aligned address).

Jim Dempsey

0 Kudos
van_der_merwe__ben
New Contributor I
662 Views

The declaration of MINDEX is given in the third code snippet above:

INTEGER MMIDEX,MSIDEX,LSIDEX,LYMSTK,LMIDEX
PARAMETER (MMIDEX=120000,MSIDEX=6000,LYMSTK=10)
INTEGER MINDEX(MMIDEX),SINDEX(MSIDEX),PMODEL,PSCLST,MOFFST,       &
&        YMSTCK(3,LYMSTK),TOPYMS
COMMON /INDEX1/ MINDEX,PMODEL,PSCLST,MOFFST,YMSTCK,TOPYMS   

There is no declaration as to any alignment. We do use /align:rec1byte

The message that Visual Studio gives:

Exception thrown at 0x4B426F3 (kbcunitop.dll) in Petro-SIM.exe: 0xC000005: Access violation reading location 0xFFFFFFFF

Does not seem consistent with the instruction at that address either, which is another odd thing.

There are no relevant DEC declarations involved.

And we have many thousands of Fortran files that get compiled and linked in. The problem only happens in this one file.

Maybe it is that the indexes definition are common and included somewhere else with some sort of compiler option?

0 Kudos
van_der_merwe__ben
New Contributor I
662 Views

Sadly that definition is included in about 406 Fortran fies, and many of them include other things above or below it.

0 Kudos
jimdempseyatthecove
Honored Contributor III
662 Views

benifck,

It is possible that error has nothing to do with your code. Assuming the error message is correct, then the only likely candidate is that BDINDX had been entered at a non-instruction start address via an errant branch.

Can you determine if this occurs on the first call or after the first call?
Can you determine if this occurs during a call or exclusive of a call?

Careful, if the cause is external to the code itself, then any changes (e.g. adding a PRINT trace) may make the symptoms move elsewhere. An then this may make it difficult to locate the source of the problem.

Regardless of the above questions, movdqa is a instruction that requires the _mm128 argument to be on a 16-byte aligned address. Per your disassembly listing it is not.

As an alternative work around, you could compiler this one file with /Qvec-

If this corrects the problem, then this indeed is indicative of a compiler code generation problem and should be reported to the Premier Support site.

Jim Dempsey

0 Kudos
van_der_merwe__ben
New Contributor I
662 Views

Can you determine if this occurs during a call or exclusive of a call?

> Yes, it is on the very first call. 100% repeatable.

Can you determine if this occurs during a call or exclusive of a call?

> This happens during a normal proper execution of a call. The call stack and everything seems fine and as expected.

My guess is that the Intel compiler is somehow optimizing incorrectly or that somehow MINDEX is not on a 16 byte boundary as the compiler expected. What could cause that? Some DEC setting for which I can search? Is it somehow included in a Fortran file elsewhere which causes this? Is there a DEC align option that I can search for? Maybe the compiler sees one where it actually handles MINDEX but then when it compiles this routine it assumes it is aligned? Yes in my standalone setup I cannot make it generate the same assembly language. Will try a few more times.

As for the error message, I suspect visual studio is generating a wrong error message.

0 Kudos
Steven_L_Intel1
Employee
662 Views

MINDEX is an integer array at the beginning of COMMON, so I would expect it to be 32 or even 64-byte aligned. If you open a memory window and ask for LOC(MINDEX), what address does it show you?

When you look to see which instruction is at fault, is this in the same run that gets the error? (In other words, are you running in the debugger and it faults there?) I ask because the load addresses will vary between runs due to Address Space Layout Randomization.

It would be interesting to set a breakpoint on that instruction (you may have to stop in the routine first and then find it) and see what the values of register ecx is before the instruction executes. Also interesting to see if it crashes the first time it hits that instruction or sometime later.

But it may well be that the compiler is improperly making an assumption here about alignment. If so, we'd need a complete test case to show the developers.

0 Kudos
Reply