- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
for some characters (in fact, those with ascii codes greater than 127), I observe different results depending on whether an `if-else` or a `select case` is used. Here is a minimal example that reproduces the issue:
use iso_fortran_env
implicit none
integer, parameter :: ascii = selected_char_kind ("ascii")
character(kind=ascii,len=1), parameter :: C1 = achar(128)
character(kind=ascii,len=1) :: myc = C1
print*,'1) With select case:'
select case ( myc )
case ( C1 )
print*,' myc = C1'
case default
print*,' myc /= C1 (problem!)'
end select
print*,'2) With if-else:'
if ( myc == C1 ) then
print*,' myc = C1'
else
print*,' myc /= C1 (problem!)'
end if
end
When compiled with ifx 2024.1.2 I get:
1) With select case:
myc /= C1 (problem!)
2) With if-else:
myc = C1
No problem observed:
- when C1 = achar(from 0 to127).
- with other compilers (ifort, gfortran, nagfor)
Thanks
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I can easily reproduce this. Looking at the run-time assembly code I see this:
The movsx does a sign-extended move of myc into register rax. The code then subtracts 128 and does a branch-if-equal to the C1 case. The problem is the sign extension, which should not have been done for a character value, messing up the compare. Compiler bug.
What's REALLY strange to me, though, is that if I ask for an assembly listing, I see different instructions. movsbq would be correct here. I'm not sure why the sub is in the assembly listing as subq, as that does not seem to be a valid mnemonic.
movsbq _UNNAMED_MAIN$$$MYC(%rip), %rax
subq $128, %rax
je .LBB0_2
jmp .LBB0_1
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
A bug report has been opened. We will fix it in the future product.
Regarding the different instructions showed in the VS debugging window and asm listing it is because by default ifx will generate the assembler output file in AT&T* syntax which is different from the Intel syntax in the debugging window. On Linux it can be changed with "-masm=intel" option.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks, but that should not change the movsx to a movsbq, an entirely different instruction. If it had actually generated movsbq, the bug would not be there.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Steve, in AT&T* syntax "movsbq" is the same instruction as "movsx" in Intel syntax. I found a online doc https://docs.oracle.com/cd/E53394_01/pdf/E54851.pdf which provides the mapping between these two sets of mnemonics. (movsbq is at page 38).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Ah, ok. I was looking at a different reference. In that case, both movsx and movsbq are wrong in the generated code.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page