|
forums.silverfrost.com Welcome to the Silverfrost forums
|
View previous topic :: View next topic |
Author |
Message |
DietmarSiepmann
Joined: 03 Jun 2013 Posts: 279
|
Posted: Wed Mar 15, 2017 1:24 pm Post subject: Common block problem |
|
|
The following code (named test_common_block1.for) uses a common block; the 64 bit executable created from test_common_block1.for via ftn95 8.10 produces strange results at runtime and strange behaviour when debugging.
Both the strange results and behaviour do not occur if compiling a 32 bit executable (with ftn95 8.10) or if deactivating/commenting the common block statement for the 64 bit executable.
Code of progamme test_common_block1.for: Code: |
LOGICAL*2 LOGLLT,LOGHSP
COMMON /COMIW2/ LOGLLT
LOGLLT=.FALSE.
LOGHSP=.FALSE.
write(*,*) 'LOGLLT=',LOGLLT,', LOGHSP=',LOGHSP
IF(LOGLLT .OR. LOGHSP) THEN
write(*,*) 'In if: LOGLLT=',LOGLLT,', LOGHSP=',LOGHSP
ENDIF
END |
Problem: the 64 bit executable executes the write statement within the second if clause although both LOGLLT and LOGHSP are set to .FALSE.
Moreover when debugging (using sdbg64), line 9 which is "IF(LOGLLT .OR. LOGHSP) THEN" is not marked with a dot at the leftmost position shown in the debugger.
Now, if I comment out the line with the common block (resulting in file test_common_block2.for), the second print statement is not executed
(as I would expect) and the line mentioned above is marked properly with a dot within the debugger.
Code of progamme test_common_block2.for: Code: |
LOGICAL*2 LOGLLT,LOGHSP
C COMMON /COMIW2/ LOGLLT
LOGLLT=.FALSE.
LOGHSP=.FALSE.
write(*,*) 'LOGLLT=',LOGLLT,', LOGHSP=',LOGHSP
IF(LOGLLT .OR. LOGHSP) THEN
write(*,*) 'In if: LOGLLT=',LOGLLT,', LOGHSP=',LOGHSP
ENDIF
END |
Moreover, if I change the if clause in test_common_block1.for in line 9 from "IF(LOGLLT .OR. LOGHSP) THEN" to "IF(LOGLLT) THEN" , resulting in file test_common_block3.for, then the second write statement is not excuted for the 64 bit executable created; however, the debugger sdbg64 does not mark the if clause with a dot. Code: | LOGICAL*2 LOGLLT,LOGHSP
COMMON /COMIW2/ LOGLLT
LOGLLT=.FALSE.
LOGHSP=.FALSE.
write(*,*) 'LOGLLT=',LOGLLT,', LOGHSP=',LOGHSP
IF(LOGLLT) THEN
write(*,*) 'In if: LOGLLT=',LOGLLT,', LOGHSP=',LOGHSP
ENDIF
END |
Compile statements for file test_common_block1.for:
ftn95 /64 test_common_block1.for /debug /link
ftn95 test_common_block1.for /debug /link
ftn95 version information: (ftn95 -Vers)
Version: 8.10.0
Built: Sat Feb 11 12:23:39 2017
Regards,
Dietmar |
|
Back to top |
|
|
mecej4
Joined: 31 Oct 2006 Posts: 1886
|
Posted: Wed Mar 15, 2017 2:22 pm Post subject: |
|
|
There is a quirk in the X64 instruction set that FTN95-64 does not account for. The 16-bit logical variable is loaded from the base of the common block into register RBX with the instructions
MOV_Q R15,Address of /COMIW2/ Block 0
MOV_H RBX,[R15]
The mnemonic used by Silverfrost tends to obscure the reality that only the 16-bit portion, i.e., BX, is being loaded, and in the X64 architecture, see https://msdn.microsoft.com/en-us/library/windows/hardware/ff561499(v=vs.85).aspx,
Quote: | Operations that output to a 32-bit subregister are automatically zero-extended to the entire 64-bit register. Operations that output to 8-bit or 16-bit subregisters are not zero-extended |
Thus, the (unnamed) upper 16 bits of EBX contain junk, which will cause the subsequent comparison of EBX to malfunction.
The fix is to have the compiler emit a MOVZX instruction instead of a MOVH instruction.
This property also applies to 32-bit code, but FTN95 correctly generates a MOVZX ECX instruction in that mode.
On the user's side, it is best to avoid 8-bit and 16-bit variables in 64-bit programs, i.e., use LOGICAL instead of LOGICAL*2, etc.
Last edited by mecej4 on Wed Mar 15, 2017 3:08 pm; edited 4 times in total |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7924 Location: Salford, UK
|
Posted: Wed Mar 15, 2017 2:36 pm Post subject: |
|
|
Thank you for this report. I have logged it as a bug that needs to be fixed.
I assume that default LOGICAL (rather than LOGICAL*2) works OK. |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7924 Location: Salford, UK
|
Posted: Wed Mar 15, 2017 5:33 pm Post subject: |
|
|
This bug in 64 bit FTN95 has been fixed for the next release.
The problem with SDBG64 has been noted. |
|
Back to top |
|
|
DietmarSiepmann
Joined: 03 Jun 2013 Posts: 279
|
Posted: Wed Mar 15, 2017 6:19 pm Post subject: |
|
|
Paul,
yes, the code generation works and produces the correct output, if I change LOGICAL*2 to LOGICAL. However, the debugger (sdbg64) still does not show the correct dots.
Code: |
LOGICAL LOGLLT,LOGHSP
COMMON /COMIW2/ LOGLLT
LOGLLT=.FALSE.
LOGHSP=.FALSE.
write(*,*) 'LOGLLT=',LOGLLT,', LOGHSP=',LOGHSP
IF(LOGLLT .OR. LOGHSP) THEN
write(*,*) 'In if: LOGLLT=',LOGLLT,', LOGHSP=',LOGHSP
ENDIF
END |
Lines 1,5,7,9,10,11 of the code begin with a dot in the debugger session, lines 2,3,4,6,8 do not! This is very confusing to me because I do not know if the if clause is active or not in a debuger session. I know I can check this out by using the cmd tool and assinging value .TRUE. to e.g. LOGLLT via the let statement within the debugger.
Oops, I have seen, the ftn95 problem will have been solved in the next release. Thanks.
mecej4,
thanks for the information. For the time being I would try using LOGICAL instead of LOGICAL*2. But we are highly interested to create 64 bit executables because we would like to make use of the bigger address space (in comparison to the 32 bit version of the same code). If I mapped LOGICAL*2 to LOGICAL , wouldn't I reduce the space for other data to be loaded unneccessarily? I should say that we make the effort of porting one of our 32 executables to 64 bit, because we would like to load as much dtat to memory as possible.
Regards,
Dietmar
Regards,
Dietmar |
|
Back to top |
|
|
mecej4
Joined: 31 Oct 2006 Posts: 1886
|
Posted: Wed Mar 15, 2017 7:16 pm Post subject: Re: |
|
|
DietmarSiepmann wrote: | If I mapped LOGICAL*2 to LOGICAL , wouldn't I reduce the space for other data to be loaded unneccessarily? ... because we would like to load as much data to memory as possible.
|
Yes. However, you want your 64-bit program to run as fast as possible with bigger data sets, no? And that is where you have to make a compromise.
In theory, you could make logical variables occupy just one bit -- a LOGICAL*1/8, so to speak. Since X64 uses 32- and 64-bit registers in most instructions, with smaller data sizes you would have to extend the input bit/byte/half-word into a register, do processing, and update memory with the contents of a small part of a register. All this sizing up/down, if done many times, can slow down your program considerably.
Perhaps, you could run some tests to help yourself to decide whether to use default LOGICAL or LOGICAL*2. |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|