- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello!
Some time ago a reported a problem with global variables which are passed as argument to functions, and later, in some calls it was updated. See more here, https://community.intel.com/t5/Intel-Fortran-Compiler/common-variable-passed-as-argument-of-function-is-overoptimized/m-p/1573128
I have tried to implement a static check into LLVM Flang to verify our source code, and for testing of my implementation, I have created the following example:
==> alloc.f90 <==
integer function alloc(n)
use common_mod
implicit none
integer n
alloc = imem + n
imem = imem + n
print_char => print_B
end function alloc
==> common.f90 <==
module print_mod
implicit none
abstract interface
subroutine print_char_t()
end subroutine print_char_t
end interface
end module print_mod
module common_mod
use print_mod, only: print_char_t
implicit none
private
integer, pointer :: imem => null()
procedure(print_char_t), pointer :: print_char
public :: imem, print_char, print_A, print_B
contains
subroutine print_A()
print *, 'A'
end subroutine print_A
subroutine print_B()
print *, 'B'
end subroutine print_B
end module common_mod
==> main.f90 <==
program main
use common_mod
implicit none
integer, target :: real_mem
interface
subroutine test(i, f)
use print_mod
integer, pointer :: i
procedure(print_char_t), pointer :: f
end subroutine test
end interface
real_mem=0
imem=>real_mem
print_char=>print_A
call print_char()
call test(imem, print_char)
call print_char()
end program main
==> test.f90 <==
subroutine test(imem2, func)
use common_mod, only: imem
use print_mod
implicit none
integer, pointer :: imem2
procedure(print_char_t), pointer, intent(inout) :: func
integer :: res
integer, external :: alloc
print *, imem2, imem
call func()
res = alloc(8)
print *, imem2, imem
call func()
end subroutine test
However, it does not work well with ifx. With optimizations it gives a quite strange answer:
$ ifx common.f90 alloc.f90 test.f90 main.f90 -O3 && ./a.out
A
0 0
A
8 8
A
B
That, pointer to function was a constant in procedure test.
Without, it is OK:
$ ifx common.f90 alloc.f90 test.f90 main.f90 -O0 && ./a.out
A
0 0
A
8 8
B
B
gfortran -O0/-O3, flang-new (Clang 20.0Git) -O0/-O3, ifort -O0/-O3 generates the same output as ifx -O0.
So, it looks like a bug in ifx. And it would be wonderful to have the same (consistent) behaviour between ifx/gfortran/flang-new not only with pointer attribute, but also without it.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'll take a look into this with the current code branches and report back.
ron
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I combined the sources to one source to help with the analysis.
cat common.f90 alloc.f90 test.f90 main.f90 >> repro.f90
Indeed, ifx is behaving differently. Using opt-bisect-limit I've isolated the difference at opt phase
EarlyCSEPass
There is a LLVM bug report on this function but it seems completely unrelated to your test case.
EarlyCSEPass In my compiler is optimization 421. 420 naturally abides.
If you've not used opt-bisect-limit here is how to do it - binary search on the optimization numbers
ifx -O3 -mllvm -opt-bisect-limit=420 repro.f90 && ./a.out
this works, 420 friendly ( I can't make this stuff up)
and this does not
ifx -O3 -mllvm -opt-bisect-limit=421 repro.f90 && ./a.out
I have what I need to dig in deeper. This issue is also present in the 2025.0 branch and the main branch "2025.1".
I will now see if I can reduce this test case down some more.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I wrote it up, bug ID is CMPLRLLVM-62428
I was wrong on the optimization phase. It's actually further up the list.
O3 is
BISECT: running pass (86) InstCombinePass on test_
O2 also points to InstCombinePass on test_
BISECT: running pass (78) InstCombinePass on test_
Optimizer bug it appears, although it is possible we are lowering test() with a missing attribute from our front end. I'm letting the optimizer team take a look first.
Here's what I reduced this to:
module print_mod
implicit none
abstract interface
subroutine print_char_t()
end subroutine print_char_t
end interface
end module print_mod
module common_mod
use print_mod, only: print_char_t
implicit none
private
procedure(print_char_t), pointer :: print_char
public :: print_char, print_A, print_B
contains
subroutine print_A()
print *, 'A'
end subroutine print_A
subroutine print_B()
print *, 'B'
end subroutine print_B
end module common_mod
integer function alloc()
use common_mod
implicit none
alloc = 42
print_char => print_B
end function alloc
subroutine test( func)
use print_mod
implicit none
procedure(print_char_t), pointer, intent(inout) :: func
integer :: res
integer, external :: alloc
print*, "calling print A"
print*, " then call alloc() sets func ptr to print B. should see A followed by B "
call func()
!...rwg commenting out both of the following print
!...rwg statements will give wrong results for func ptr
!...rwg uncomment either print will set func ptr to B as it should be
!print*, "calling alloc, setting func ptr to print B"
res = alloc()
!print*, "done with alloc, call func to print B"
call func()
end subroutine test
program main
use common_mod
implicit none
interface
subroutine test(f)
use common_mod
use print_mod
procedure(print_char_t), pointer, intent(inout) :: f
end subroutine test
end interface
print_char=>print_A
print*, "calling test"
call test(print_char)
print*, "done with test, should be print B"
call print_char()
end program main
This is one of those tricky bugs. Notice my comments around the call to alloc() at line 46. There is a print before and a print after the call, commented out. If you uncomment one or the other RPINT the code works at O1-O3!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Not in the optimizer, it's in our Fortran frontend code. We know the problem, working on a fix.
I am curious, is this blocking you from moving your application to ifx? If so, what is the name of your project or application, assuming you can share that information.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yep, it is blocking. The project is MRCC developed in BME. Project page is mrcc.hu
I have replaced all places where this bug happens, however, I do not know the status of my patches... If you interested, I can add you into GitHub repo. It is my own development ahead of master branch.
If somebody push Prof. Mihaly Kallay to use git, I will be extremely happy
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page