* FINAL subroutines @ 2022-01-24 13:50 Salvatore Filippone 2022-01-24 14:49 ` Salvatore Filippone 0 siblings, 1 reply; 10+ messages in thread From: Salvatore Filippone @ 2022-01-24 13:50 UTC (permalink / raw) To: Fortran List [-- Attachment #1: Type: text/plain, Size: 2162 bytes --] Hi all The attached code compiles and runs fine under both GNU and Intel, but it produces different results, in particular the FINAL subroutine is invoked just once with GNU, three times with Intel. It seems to me that they cannot both be right; I am not sure what the standard is mandating in this case. Any ideas? Salvatore --------------- Intel [pr1eio03@login1: newstuff]$ ifort -v ifort version 19.1.1.217 [pr1eio03@login1: newstuff]$ ifort -o testfinal testfinal.f90 [pr1eio03@login1: newstuff]$ ./testfinal Allocating wrapper Calling new_outer_type Assigning outer%test_item Called delete_test_type Called delete_test_type End of new_outer_type DeAllocating wrapper Called delete_test_type ----------------------------- GNU sfilippo@lagrange newstuff]$ gfortran -v Using built-in specs. COLLECT_GCC=gfortran COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/11/lto-wrapper OFFLOAD_TARGET_NAMES=nvptx-none OFFLOAD_TARGET_DEFAULT=1 Target: x86_64-redhat-linux Configured with: ../configure --enable-bootstrap --enable-languages=c,c++,fortran,objc,obj-c++,ada,go,d,lto --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl= http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-gcc-major-version-only --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --with-isl=/builddir/build/BUILD/gcc-11.2.1-20210728/obj-x86_64-redhat-linux/isl-install --enable-offload-targets=nvptx-none --without-cuda-driver --enable-gnu-indirect-function --enable-cet --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux Thread model: posix Supported LTO compression algorithms: zlib zstd gcc version 11.2.1 20210728 (Red Hat 11.2.1-1) (GCC) [sfilippo@lagrange newstuff]$ gfortran -o testfinal testfinal.f90 [sfilippo@lagrange newstuff]$ ./testfinal Allocating wrapper Calling new_outer_type Assigning outer%test_item End of new_outer_type DeAllocating wrapper Called delete_test_type --------------------- [-- Attachment #2: testfinal.f90 --] [-- Type: text/x-fortran, Size: 1460 bytes --] module test_type_mod type :: my_test_type integer, allocatable :: i contains final :: delete_test_type end type my_test_type interface my_test_type module procedure new_test_type_object end interface my_test_type contains subroutine delete_test_type(this) type(my_test_type) :: this write(*,*) 'Called delete_test_type' if (allocated(this%i)) deallocate(this%i) end subroutine delete_test_type function new_test_type_object(item) result(res) type(my_test_type) :: res integer, intent(in) :: item !Allocation on assignment res%i=item end function new_test_type_object end module test_type_mod module target_mod use test_type_mod type :: outer_type type(my_test_type), allocatable :: test_item end type outer_type contains subroutine new_outer_type(outer,item) type(outer_type), intent(out) :: outer integer :: item allocate(outer%test_item) write(*,*) 'Assigning outer%test_item' outer%test_item = my_test_type(itemi) write(*,*) 'End of new_outer_type' end subroutine new_outer_type end module target_mod program testfinal use target_mod implicit none integer :: i=10 type(outer_type), allocatable :: wrapper write(*,*) 'Allocating wrapper ' allocate(wrapper) write(*,*) 'Calling new_outer_type ' call new_outer_type(wrapper,i) write(*,*) 'DeAllocating wrapper ' deallocate(wrapper) end program testfinal ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: FINAL subroutines 2022-01-24 13:50 FINAL subroutines Salvatore Filippone @ 2022-01-24 14:49 ` Salvatore Filippone 2022-01-24 15:45 ` Andrew Benson 0 siblings, 1 reply; 10+ messages in thread From: Salvatore Filippone @ 2022-01-24 14:49 UTC (permalink / raw) To: Fortran List And here is the code embedded as text............ sorry about sending an attachment that was purged ------------------------- testfinal.f90 --------------------- module test_type_mod type :: my_test_type integer, allocatable :: i contains final :: delete_test_type end type my_test_type interface my_test_type module procedure new_test_type_object end interface my_test_type contains subroutine delete_test_type(this) type(my_test_type) :: this write(*,*) 'Called delete_test_type' if (allocated(this%i)) deallocate(this%i) end subroutine delete_test_type function new_test_type_object(item) result(res) type(my_test_type) :: res integer, intent(in) :: item !Allocation on assignment res%i=item end function new_test_type_object end module test_type_mod module target_mod use test_type_mod type :: outer_type type(my_test_type), allocatable :: test_item end type outer_type contains subroutine new_outer_type(outer,item) type(outer_type), intent(out) :: outer integer :: item allocate(outer%test_item) write(*,*) 'Assigning outer%test_item' outer%test_item = my_test_type(itemi) write(*,*) 'End of new_outer_type' end subroutine new_outer_type end module target_mod program testfinal use target_mod implicit none integer :: i=10 type(outer_type), allocatable :: wrapper write(*,*) 'Allocating wrapper ' allocate(wrapper) write(*,*) 'Calling new_outer_type ' call new_outer_type(wrapper,i) write(*,*) 'DeAllocating wrapper ' deallocate(wrapper) end program testfinal On Mon, Jan 24, 2022 at 2:50 PM Salvatore Filippone < filippone.salvatore@gmail.com> wrote: > Hi all > The attached code compiles and runs fine under both GNU and Intel, but it > produces different results, in particular the FINAL subroutine is invoked > just once with GNU, three times with Intel. > > It seems to me that they cannot both be right; I am not sure what the > standard is mandating in this case. > Any ideas? > Salvatore > --------------- Intel > [pr1eio03@login1: newstuff]$ ifort -v > ifort version 19.1.1.217 > [pr1eio03@login1: newstuff]$ ifort -o testfinal testfinal.f90 > [pr1eio03@login1: newstuff]$ ./testfinal > Allocating wrapper > Calling new_outer_type > Assigning outer%test_item > Called delete_test_type > Called delete_test_type > End of new_outer_type > DeAllocating wrapper > Called delete_test_type > ----------------------------- GNU > sfilippo@lagrange newstuff]$ gfortran -v > Using built-in specs. > COLLECT_GCC=gfortran > COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/11/lto-wrapper > OFFLOAD_TARGET_NAMES=nvptx-none > OFFLOAD_TARGET_DEFAULT=1 > Target: x86_64-redhat-linux > Configured with: ../configure --enable-bootstrap > --enable-languages=c,c++,fortran,objc,obj-c++,ada,go,d,lto --prefix=/usr > --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl= > http://bugzilla.redhat.com/bugzilla --enable-shared > --enable-threads=posix --enable-checking=release --enable-multilib > --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions > --enable-gnu-unique-object --enable-linker-build-id > --with-gcc-major-version-only --with-linker-hash-style=gnu --enable-plugin > --enable-initfini-array > --with-isl=/builddir/build/BUILD/gcc-11.2.1-20210728/obj-x86_64-redhat-linux/isl-install > --enable-offload-targets=nvptx-none --without-cuda-driver > --enable-gnu-indirect-function --enable-cet --with-tune=generic > --with-arch_32=i686 --build=x86_64-redhat-linux > Thread model: posix > Supported LTO compression algorithms: zlib zstd > gcc version 11.2.1 20210728 (Red Hat 11.2.1-1) (GCC) > [sfilippo@lagrange newstuff]$ gfortran -o testfinal testfinal.f90 > [sfilippo@lagrange newstuff]$ ./testfinal > Allocating wrapper > Calling new_outer_type > Assigning outer%test_item > End of new_outer_type > DeAllocating wrapper > Called delete_test_type > --------------------- > > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: FINAL subroutines 2022-01-24 14:49 ` Salvatore Filippone @ 2022-01-24 15:45 ` Andrew Benson 2022-01-24 16:11 ` Salvatore Filippone 0 siblings, 1 reply; 10+ messages in thread From: Andrew Benson @ 2022-01-24 15:45 UTC (permalink / raw) To: Salvatore Filippone; +Cc: Fortran List Hi Salvatore, This looks like it's related to some of the missing finalization functionality (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37336). Paul has some patches (e.g. https://gcc.gnu.org/pipermail/fortran/2022-January/057415.html) which implement most of the missing functionality. With those patches incorporated your code gives the following output with gfortran: $ ./testfinal Allocating wrapper Calling new_outer_type Assigning outer%test_item Called delete_test_type End of new_outer_type DeAllocating wrapper Called delete_test_type So there is one more call to the finalizer than you found - I haven't checked carefully but I would guess this is a deallocation of LHS on assignment. In testing these patches using the Intel compiler we found that it seems to call the finalization wrapper more than it should, sometimes on objects that have already been deallocated. Your code, compiled with the Intel compiler and then run under valgrind shows the following: $ valgrind ./testfinal ==7340== Memcheck, a memory error detector ==7340== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==7340== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info ==7340== Command: ./testfinal ==7340== ==7340== Conditional jump or move depends on uninitialised value(s) ==7340== at 0x493A51: __intel_sse2_strcpy (in /home/abensonca/Scratch/ ifortTests/testfinal) ==7340== by 0x45D70E: for__add_to_lf_table (in /home/abensonca/Scratch/ ifortTests/testfinal) ==7340== by 0x4410CB: for__open_proc (in /home/abensonca/Scratch/ ifortTests/testfinal) ==7340== by 0x423A64: for__open_default (in /home/abensonca/Scratch/ ifortTests/testfinal) ==7340== by 0x4305A9: for_write_seq_lis (in /home/abensonca/Scratch/ ifortTests/testfinal) ==7340== by 0x4047E1: MAIN__ (testfinal.f90:62) ==7340== by 0x403CE1: main (in /home/abensonca/Scratch/ifortTests/ testfinal) ==7340== Allocating wrapper Calling new_outer_type Assigning outer%test_item Called delete_test_type ==7340== Conditional jump or move depends on uninitialised value(s) ==7340== at 0x40572A: do_alloc_copy (in /home/abensonca/Scratch/ifortTests/ testfinal) ==7340== by 0x406B9A: do_alloc_copy (in /home/abensonca/Scratch/ifortTests/ testfinal) ==7340== by 0x4084ED: for_alloc_assign_v2 (in /home/abensonca/Scratch/ ifortTests/testfinal) ==7340== by 0x404474: target_mod_mp_new_outer_type_ (testfinal.f90:48) ==7340== by 0x40485E: MAIN__ (testfinal.f90:65) ==7340== by 0x403CE1: main (in /home/abensonca/Scratch/ifortTests/ testfinal) ==7340== Called delete_test_type End of new_outer_type DeAllocating wrapper Called delete_test_type ==7340== ==7340== HEAP SUMMARY: ==7340== in use at exit: 48 bytes in 1 blocks ==7340== total heap usage: 14 allocs, 13 frees, 12,879 bytes allocated ==7340== ==7340== LEAK SUMMARY: ==7340== definitely lost: 48 bytes in 1 blocks ==7340== indirectly lost: 0 bytes in 0 blocks ==7340== possibly lost: 0 bytes in 0 blocks ==7340== still reachable: 0 bytes in 0 blocks ==7340== suppressed: 0 bytes in 0 blocks ==7340== Rerun with --leak-check=full to see details of leaked memory ==7340== ==7340== For counts of detected and suppressed errors, rerun with: -v ==7340== Use --track-origins=yes to see where uninitialised values come from ==7340== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) so there are some cases of what look like incorrect accesses (and some leaked memory). Your code compiled with gfortran (with Paul's patches in place) shows no errors or leaks from valgrind. So, in summary, in this case I think the current gfortran is missing some finalizations (which are fixed by Paul's patches), and ifort is likely doing something wrong and probably calling the finalizer more times than it should. -Andrew On Monday, January 24, 2022 6:49:23 AM PST Salvatore Filippone via Fortran wrote: > And here is the code embedded as text............ sorry about sending an > attachment that was purged > ------------------------- testfinal.f90 --------------------- > module test_type_mod > > type :: my_test_type > integer, allocatable :: i > contains > final :: delete_test_type > end type my_test_type > > interface my_test_type > module procedure new_test_type_object > end interface my_test_type > > contains > > subroutine delete_test_type(this) > type(my_test_type) :: this > > write(*,*) 'Called delete_test_type' > if (allocated(this%i)) deallocate(this%i) > > end subroutine delete_test_type > > > function new_test_type_object(item) result(res) > type(my_test_type) :: res > integer, intent(in) :: item > !Allocation on assignment > res%i=item > end function new_test_type_object > > > end module test_type_mod > > module target_mod > use test_type_mod > type :: outer_type > type(my_test_type), allocatable :: test_item > end type outer_type > > contains > > subroutine new_outer_type(outer,item) > type(outer_type), intent(out) :: outer > integer :: item > > allocate(outer%test_item) > write(*,*) 'Assigning outer%test_item' > outer%test_item = my_test_type(itemi) > write(*,*) 'End of new_outer_type' > end subroutine new_outer_type > > end module target_mod > > program testfinal > use target_mod > > implicit none > > integer :: i=10 > type(outer_type), allocatable :: wrapper > > write(*,*) 'Allocating wrapper ' > allocate(wrapper) > write(*,*) 'Calling new_outer_type ' > call new_outer_type(wrapper,i) > write(*,*) 'DeAllocating wrapper ' > deallocate(wrapper) > > end program testfinal > > On Mon, Jan 24, 2022 at 2:50 PM Salvatore Filippone < > > filippone.salvatore@gmail.com> wrote: > > Hi all > > The attached code compiles and runs fine under both GNU and Intel, but it > > produces different results, in particular the FINAL subroutine is invoked > > just once with GNU, three times with Intel. > > > > It seems to me that they cannot both be right; I am not sure what the > > standard is mandating in this case. > > Any ideas? > > Salvatore > > --------------- Intel > > [pr1eio03@login1: newstuff]$ ifort -v > > ifort version 19.1.1.217 > > [pr1eio03@login1: newstuff]$ ifort -o testfinal testfinal.f90 > > [pr1eio03@login1: newstuff]$ ./testfinal > > > > Allocating wrapper > > Calling new_outer_type > > Assigning outer%test_item > > Called delete_test_type > > Called delete_test_type > > End of new_outer_type > > DeAllocating wrapper > > Called delete_test_type > > > > ----------------------------- GNU > > sfilippo@lagrange newstuff]$ gfortran -v > > Using built-in specs. > > COLLECT_GCC=gfortran > > COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/11/lto-wrapper > > OFFLOAD_TARGET_NAMES=nvptx-none > > OFFLOAD_TARGET_DEFAULT=1 > > Target: x86_64-redhat-linux > > Configured with: ../configure --enable-bootstrap > > --enable-languages=c,c++,fortran,objc,obj-c++,ada,go,d,lto --prefix=/usr > > --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl= > > http://bugzilla.redhat.com/bugzilla --enable-shared > > --enable-threads=posix --enable-checking=release --enable-multilib > > --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions > > --enable-gnu-unique-object --enable-linker-build-id > > --with-gcc-major-version-only --with-linker-hash-style=gnu --enable-plugin > > --enable-initfini-array > > --with-isl=/builddir/build/BUILD/gcc-11.2.1-20210728/obj-x86_64-redhat-lin > > ux/isl-install --enable-offload-targets=nvptx-none --without-cuda-driver > > --enable-gnu-indirect-function --enable-cet --with-tune=generic > > --with-arch_32=i686 --build=x86_64-redhat-linux > > Thread model: posix > > Supported LTO compression algorithms: zlib zstd > > gcc version 11.2.1 20210728 (Red Hat 11.2.1-1) (GCC) > > [sfilippo@lagrange newstuff]$ gfortran -o testfinal testfinal.f90 > > [sfilippo@lagrange newstuff]$ ./testfinal > > > > Allocating wrapper > > Calling new_outer_type > > Assigning outer%test_item > > End of new_outer_type > > DeAllocating wrapper > > Called delete_test_type > > > > --------------------- -- * Andrew Benson: https://abensonca.github.io * Galacticus: https://github.com/galacticusorg/galacticus ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: FINAL subroutines 2022-01-24 15:45 ` Andrew Benson @ 2022-01-24 16:11 ` Salvatore Filippone 2022-01-26 21:29 ` Jerry D 0 siblings, 1 reply; 10+ messages in thread From: Salvatore Filippone @ 2022-01-24 16:11 UTC (permalink / raw) To: Andrew Benson; +Cc: Fortran List, Damian Rouson Thanks a lot (yes, I suspected both gfortran and intel were wrong, precisely because I could see why you'd need two FINAL calls, but not three). Salvatore On Mon, Jan 24, 2022 at 4:45 PM Andrew Benson <abenson@carnegiescience.edu> wrote: > Hi Salvatore, > > This looks like it's related to some of the missing finalization > functionality > (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37336). Paul has some > patches > (e.g. https://gcc.gnu.org/pipermail/fortran/2022-January/057415.html) > which > implement most of the missing functionality. With those patches > incorporated > your code gives the following output with gfortran: > > $ ./testfinal > Allocating wrapper > Calling new_outer_type > Assigning outer%test_item > Called delete_test_type > End of new_outer_type > DeAllocating wrapper > Called delete_test_type > > So there is one more call to the finalizer than you found - I haven't > checked > carefully but I would guess this is a deallocation of LHS on assignment. > > In testing these patches using the Intel compiler we found that it seems > to > call the finalization wrapper more than it should, sometimes on objects > that > have already been deallocated. Your code, compiled with the Intel compiler > and > then run under valgrind shows the following: > > $ valgrind ./testfinal > ==7340== Memcheck, a memory error detector > ==7340== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. > ==7340== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info > ==7340== Command: ./testfinal > ==7340== > ==7340== Conditional jump or move depends on uninitialised value(s) > ==7340== at 0x493A51: __intel_sse2_strcpy (in /home/abensonca/Scratch/ > ifortTests/testfinal) > ==7340== by 0x45D70E: for__add_to_lf_table (in /home/abensonca/Scratch/ > ifortTests/testfinal) > ==7340== by 0x4410CB: for__open_proc (in /home/abensonca/Scratch/ > ifortTests/testfinal) > ==7340== by 0x423A64: for__open_default (in /home/abensonca/Scratch/ > ifortTests/testfinal) > ==7340== by 0x4305A9: for_write_seq_lis (in /home/abensonca/Scratch/ > ifortTests/testfinal) > ==7340== by 0x4047E1: MAIN__ (testfinal.f90:62) > ==7340== by 0x403CE1: main (in /home/abensonca/Scratch/ifortTests/ > testfinal) > ==7340== > Allocating wrapper > Calling new_outer_type > Assigning outer%test_item > Called delete_test_type > ==7340== Conditional jump or move depends on uninitialised value(s) > ==7340== at 0x40572A: do_alloc_copy (in > /home/abensonca/Scratch/ifortTests/ > testfinal) > ==7340== by 0x406B9A: do_alloc_copy (in > /home/abensonca/Scratch/ifortTests/ > testfinal) > ==7340== by 0x4084ED: for_alloc_assign_v2 (in /home/abensonca/Scratch/ > ifortTests/testfinal) > ==7340== by 0x404474: target_mod_mp_new_outer_type_ (testfinal.f90:48) > ==7340== by 0x40485E: MAIN__ (testfinal.f90:65) > ==7340== by 0x403CE1: main (in /home/abensonca/Scratch/ifortTests/ > testfinal) > ==7340== > Called delete_test_type > End of new_outer_type > DeAllocating wrapper > Called delete_test_type > ==7340== > ==7340== HEAP SUMMARY: > ==7340== in use at exit: 48 bytes in 1 blocks > ==7340== total heap usage: 14 allocs, 13 frees, 12,879 bytes allocated > ==7340== > ==7340== LEAK SUMMARY: > ==7340== definitely lost: 48 bytes in 1 blocks > ==7340== indirectly lost: 0 bytes in 0 blocks > ==7340== possibly lost: 0 bytes in 0 blocks > ==7340== still reachable: 0 bytes in 0 blocks > ==7340== suppressed: 0 bytes in 0 blocks > ==7340== Rerun with --leak-check=full to see details of leaked memory > ==7340== > ==7340== For counts of detected and suppressed errors, rerun with: -v > ==7340== Use --track-origins=yes to see where uninitialised values come > from > ==7340== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) > > so there are some cases of what look like incorrect accesses (and some > leaked > memory). > > Your code compiled with gfortran (with Paul's patches in place) shows no > errors or leaks from valgrind. > > So, in summary, in this case I think the current gfortran is missing some > finalizations (which are fixed by Paul's patches), and ifort is likely > doing > something wrong and probably calling the finalizer more times than it > should. > > -Andrew > > On Monday, January 24, 2022 6:49:23 AM PST Salvatore Filippone via Fortran > wrote: > > And here is the code embedded as text............ sorry about sending an > > attachment that was purged > > ------------------------- testfinal.f90 --------------------- > > module test_type_mod > > > > type :: my_test_type > > integer, allocatable :: i > > contains > > final :: delete_test_type > > end type my_test_type > > > > interface my_test_type > > module procedure new_test_type_object > > end interface my_test_type > > > > contains > > > > subroutine delete_test_type(this) > > type(my_test_type) :: this > > > > write(*,*) 'Called delete_test_type' > > if (allocated(this%i)) deallocate(this%i) > > > > end subroutine delete_test_type > > > > > > function new_test_type_object(item) result(res) > > type(my_test_type) :: res > > integer, intent(in) :: item > > !Allocation on assignment > > res%i=item > > end function new_test_type_object > > > > > > end module test_type_mod > > > > module target_mod > > use test_type_mod > > type :: outer_type > > type(my_test_type), allocatable :: test_item > > end type outer_type > > > > contains > > > > subroutine new_outer_type(outer,item) > > type(outer_type), intent(out) :: outer > > integer :: item > > > > allocate(outer%test_item) > > write(*,*) 'Assigning outer%test_item' > > outer%test_item = my_test_type(itemi) > > write(*,*) 'End of new_outer_type' > > end subroutine new_outer_type > > > > end module target_mod > > > > program testfinal > > use target_mod > > > > implicit none > > > > integer :: i=10 > > type(outer_type), allocatable :: wrapper > > > > write(*,*) 'Allocating wrapper ' > > allocate(wrapper) > > write(*,*) 'Calling new_outer_type ' > > call new_outer_type(wrapper,i) > > write(*,*) 'DeAllocating wrapper ' > > deallocate(wrapper) > > > > end program testfinal > > > > On Mon, Jan 24, 2022 at 2:50 PM Salvatore Filippone < > > > > filippone.salvatore@gmail.com> wrote: > > > Hi all > > > The attached code compiles and runs fine under both GNU and Intel, but > it > > > produces different results, in particular the FINAL subroutine is > invoked > > > just once with GNU, three times with Intel. > > > > > > It seems to me that they cannot both be right; I am not sure what the > > > standard is mandating in this case. > > > Any ideas? > > > Salvatore > > > --------------- Intel > > > [pr1eio03@login1: newstuff]$ ifort -v > > > ifort version 19.1.1.217 > > > [pr1eio03@login1: newstuff]$ ifort -o testfinal testfinal.f90 > > > [pr1eio03@login1: newstuff]$ ./testfinal > > > > > > Allocating wrapper > > > Calling new_outer_type > > > Assigning outer%test_item > > > Called delete_test_type > > > Called delete_test_type > > > End of new_outer_type > > > DeAllocating wrapper > > > Called delete_test_type > > > > > > ----------------------------- GNU > > > sfilippo@lagrange newstuff]$ gfortran -v > > > Using built-in specs. > > > COLLECT_GCC=gfortran > > > COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/11/lto-wrapper > > > OFFLOAD_TARGET_NAMES=nvptx-none > > > OFFLOAD_TARGET_DEFAULT=1 > > > Target: x86_64-redhat-linux > > > Configured with: ../configure --enable-bootstrap > > > --enable-languages=c,c++,fortran,objc,obj-c++,ada,go,d,lto > --prefix=/usr > > > --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl= > > > http://bugzilla.redhat.com/bugzilla --enable-shared > > > --enable-threads=posix --enable-checking=release --enable-multilib > > > --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions > > > --enable-gnu-unique-object --enable-linker-build-id > > > --with-gcc-major-version-only --with-linker-hash-style=gnu > --enable-plugin > > > --enable-initfini-array > > > > --with-isl=/builddir/build/BUILD/gcc-11.2.1-20210728/obj-x86_64-redhat-lin > > > ux/isl-install --enable-offload-targets=nvptx-none > --without-cuda-driver > > > --enable-gnu-indirect-function --enable-cet --with-tune=generic > > > --with-arch_32=i686 --build=x86_64-redhat-linux > > > Thread model: posix > > > Supported LTO compression algorithms: zlib zstd > > > gcc version 11.2.1 20210728 (Red Hat 11.2.1-1) (GCC) > > > [sfilippo@lagrange newstuff]$ gfortran -o testfinal testfinal.f90 > > > [sfilippo@lagrange newstuff]$ ./testfinal > > > > > > Allocating wrapper > > > Calling new_outer_type > > > Assigning outer%test_item > > > End of new_outer_type > > > DeAllocating wrapper > > > Called delete_test_type > > > > > > --------------------- > > > -- > > * Andrew Benson: https://abensonca.github.io > > * Galacticus: https://github.com/galacticusorg/galacticus > > > > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: FINAL subroutines 2022-01-24 16:11 ` Salvatore Filippone @ 2022-01-26 21:29 ` Jerry D 2022-01-26 22:59 ` Paul Richard Thomas 0 siblings, 1 reply; 10+ messages in thread From: Jerry D @ 2022-01-26 21:29 UTC (permalink / raw) To: Salvatore Filippone, Andrew Benson; +Cc: Damian Rouson, Fortran List Is there any reason these patches can not be applied and use this test as a test case? Regards, Jerry On 1/24/22 8:11 AM, Salvatore Filippone via Fortran wrote: > Thanks a lot > (yes, I suspected both gfortran and intel were wrong, precisely because I > could see why you'd need two FINAL calls, but not three). > > Salvatore > > On Mon, Jan 24, 2022 at 4:45 PM Andrew Benson <abenson@carnegiescience.edu> > wrote: > >> Hi Salvatore, >> >> This looks like it's related to some of the missing finalization >> functionality >> (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37336). Paul has some >> patches >> (e.g. https://gcc.gnu.org/pipermail/fortran/2022-January/057415.html) >> which >> implement most of the missing functionality. With those patches >> incorporated >> your code gives the following output with gfortran: >> >> $ ./testfinal >> Allocating wrapper >> Calling new_outer_type >> Assigning outer%test_item >> Called delete_test_type >> End of new_outer_type >> DeAllocating wrapper >> Called delete_test_type >> >> So there is one more call to the finalizer than you found - I haven't >> checked >> carefully but I would guess this is a deallocation of LHS on assignment. >> >> In testing these patches using the Intel compiler we found that it seems >> to >> call the finalization wrapper more than it should, sometimes on objects >> that >> have already been deallocated. Your code, compiled with the Intel compiler >> and >> then run under valgrind shows the following: >> >> $ valgrind ./testfinal >> ==7340== Memcheck, a memory error detector >> ==7340== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. >> ==7340== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info >> ==7340== Command: ./testfinal >> ==7340== >> ==7340== Conditional jump or move depends on uninitialised value(s) >> ==7340== at 0x493A51: __intel_sse2_strcpy (in /home/abensonca/Scratch/ >> ifortTests/testfinal) >> ==7340== by 0x45D70E: for__add_to_lf_table (in /home/abensonca/Scratch/ >> ifortTests/testfinal) >> ==7340== by 0x4410CB: for__open_proc (in /home/abensonca/Scratch/ >> ifortTests/testfinal) >> ==7340== by 0x423A64: for__open_default (in /home/abensonca/Scratch/ >> ifortTests/testfinal) >> ==7340== by 0x4305A9: for_write_seq_lis (in /home/abensonca/Scratch/ >> ifortTests/testfinal) >> ==7340== by 0x4047E1: MAIN__ (testfinal.f90:62) >> ==7340== by 0x403CE1: main (in /home/abensonca/Scratch/ifortTests/ >> testfinal) >> ==7340== >> Allocating wrapper >> Calling new_outer_type >> Assigning outer%test_item >> Called delete_test_type >> ==7340== Conditional jump or move depends on uninitialised value(s) >> ==7340== at 0x40572A: do_alloc_copy (in >> /home/abensonca/Scratch/ifortTests/ >> testfinal) >> ==7340== by 0x406B9A: do_alloc_copy (in >> /home/abensonca/Scratch/ifortTests/ >> testfinal) >> ==7340== by 0x4084ED: for_alloc_assign_v2 (in /home/abensonca/Scratch/ >> ifortTests/testfinal) >> ==7340== by 0x404474: target_mod_mp_new_outer_type_ (testfinal.f90:48) >> ==7340== by 0x40485E: MAIN__ (testfinal.f90:65) >> ==7340== by 0x403CE1: main (in /home/abensonca/Scratch/ifortTests/ >> testfinal) >> ==7340== >> Called delete_test_type >> End of new_outer_type >> DeAllocating wrapper >> Called delete_test_type >> ==7340== >> ==7340== HEAP SUMMARY: >> ==7340== in use at exit: 48 bytes in 1 blocks >> ==7340== total heap usage: 14 allocs, 13 frees, 12,879 bytes allocated >> ==7340== >> ==7340== LEAK SUMMARY: >> ==7340== definitely lost: 48 bytes in 1 blocks >> ==7340== indirectly lost: 0 bytes in 0 blocks >> ==7340== possibly lost: 0 bytes in 0 blocks >> ==7340== still reachable: 0 bytes in 0 blocks >> ==7340== suppressed: 0 bytes in 0 blocks >> ==7340== Rerun with --leak-check=full to see details of leaked memory >> ==7340== >> ==7340== For counts of detected and suppressed errors, rerun with: -v >> ==7340== Use --track-origins=yes to see where uninitialised values come >> from >> ==7340== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) >> >> so there are some cases of what look like incorrect accesses (and some >> leaked >> memory). >> >> Your code compiled with gfortran (with Paul's patches in place) shows no >> errors or leaks from valgrind. >> >> So, in summary, in this case I think the current gfortran is missing some >> finalizations (which are fixed by Paul's patches), and ifort is likely >> doing >> something wrong and probably calling the finalizer more times than it >> should. >> >> -Andrew >> >> On Monday, January 24, 2022 6:49:23 AM PST Salvatore Filippone via Fortran >> wrote: >>> And here is the code embedded as text............ sorry about sending an >>> attachment that was purged >>> ------------------------- testfinal.f90 --------------------- >>> module test_type_mod >>> >>> type :: my_test_type >>> integer, allocatable :: i >>> contains >>> final :: delete_test_type >>> end type my_test_type >>> >>> interface my_test_type >>> module procedure new_test_type_object >>> end interface my_test_type >>> >>> contains >>> >>> subroutine delete_test_type(this) >>> type(my_test_type) :: this >>> >>> write(*,*) 'Called delete_test_type' >>> if (allocated(this%i)) deallocate(this%i) >>> >>> end subroutine delete_test_type >>> >>> >>> function new_test_type_object(item) result(res) >>> type(my_test_type) :: res >>> integer, intent(in) :: item >>> !Allocation on assignment >>> res%i=item >>> end function new_test_type_object >>> >>> >>> end module test_type_mod >>> >>> module target_mod >>> use test_type_mod >>> type :: outer_type >>> type(my_test_type), allocatable :: test_item >>> end type outer_type >>> >>> contains >>> >>> subroutine new_outer_type(outer,item) >>> type(outer_type), intent(out) :: outer >>> integer :: item >>> >>> allocate(outer%test_item) >>> write(*,*) 'Assigning outer%test_item' >>> outer%test_item = my_test_type(itemi) >>> write(*,*) 'End of new_outer_type' >>> end subroutine new_outer_type >>> >>> end module target_mod >>> >>> program testfinal >>> use target_mod >>> >>> implicit none >>> >>> integer :: i=10 >>> type(outer_type), allocatable :: wrapper >>> >>> write(*,*) 'Allocating wrapper ' >>> allocate(wrapper) >>> write(*,*) 'Calling new_outer_type ' >>> call new_outer_type(wrapper,i) >>> write(*,*) 'DeAllocating wrapper ' >>> deallocate(wrapper) >>> >>> end program testfinal >>> >>> On Mon, Jan 24, 2022 at 2:50 PM Salvatore Filippone < >>> >>> filippone.salvatore@gmail.com> wrote: >>>> Hi all >>>> The attached code compiles and runs fine under both GNU and Intel, but >> it >>>> produces different results, in particular the FINAL subroutine is >> invoked >>>> just once with GNU, three times with Intel. >>>> >>>> It seems to me that they cannot both be right; I am not sure what the >>>> standard is mandating in this case. >>>> Any ideas? >>>> Salvatore >>>> --------------- Intel >>>> [pr1eio03@login1: newstuff]$ ifort -v >>>> ifort version 19.1.1.217 >>>> [pr1eio03@login1: newstuff]$ ifort -o testfinal testfinal.f90 >>>> [pr1eio03@login1: newstuff]$ ./testfinal >>>> >>>> Allocating wrapper >>>> Calling new_outer_type >>>> Assigning outer%test_item >>>> Called delete_test_type >>>> Called delete_test_type >>>> End of new_outer_type >>>> DeAllocating wrapper >>>> Called delete_test_type >>>> >>>> ----------------------------- GNU >>>> sfilippo@lagrange newstuff]$ gfortran -v >>>> Using built-in specs. >>>> COLLECT_GCC=gfortran >>>> COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/11/lto-wrapper >>>> OFFLOAD_TARGET_NAMES=nvptx-none >>>> OFFLOAD_TARGET_DEFAULT=1 >>>> Target: x86_64-redhat-linux >>>> Configured with: ../configure --enable-bootstrap >>>> --enable-languages=c,c++,fortran,objc,obj-c++,ada,go,d,lto >> --prefix=/usr >>>> --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl= >>>> http://bugzilla.redhat.com/bugzilla --enable-shared >>>> --enable-threads=posix --enable-checking=release --enable-multilib >>>> --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions >>>> --enable-gnu-unique-object --enable-linker-build-id >>>> --with-gcc-major-version-only --with-linker-hash-style=gnu >> --enable-plugin >>>> --enable-initfini-array >>>> >> --with-isl=/builddir/build/BUILD/gcc-11.2.1-20210728/obj-x86_64-redhat-lin >>>> ux/isl-install --enable-offload-targets=nvptx-none >> --without-cuda-driver >>>> --enable-gnu-indirect-function --enable-cet --with-tune=generic >>>> --with-arch_32=i686 --build=x86_64-redhat-linux >>>> Thread model: posix >>>> Supported LTO compression algorithms: zlib zstd >>>> gcc version 11.2.1 20210728 (Red Hat 11.2.1-1) (GCC) >>>> [sfilippo@lagrange newstuff]$ gfortran -o testfinal testfinal.f90 >>>> [sfilippo@lagrange newstuff]$ ./testfinal >>>> >>>> Allocating wrapper >>>> Calling new_outer_type >>>> Assigning outer%test_item >>>> End of new_outer_type >>>> DeAllocating wrapper >>>> Called delete_test_type >>>> >>>> --------------------- >> >> -- >> >> * Andrew Benson: https://abensonca.github.io >> >> * Galacticus: https://github.com/galacticusorg/galacticus >> >> >> >> ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: FINAL subroutines 2022-01-26 21:29 ` Jerry D @ 2022-01-26 22:59 ` Paul Richard Thomas 2022-01-27 7:17 ` Salvatore Filippone 0 siblings, 1 reply; 10+ messages in thread From: Paul Richard Thomas @ 2022-01-26 22:59 UTC (permalink / raw) To: Jerry D; +Cc: Salvatore Filippone, Andrew Benson, Damian Rouson, Fortran List Hi Jerry, I am trying to fix the failure of my latest patch with this very test case. Otherwise it fixes most of the remaining dependencies in PR37336. At a pinch, I could submit the earlier patch that Andrew mentions and work from there. However, you will note that it does miss one of the finalizations. This is critical because function results, which should be finalized, are not. I'll keep an eye on the state of the branch. By and large, release occurs 3-4 months after the start of stage 4. I will leave 2 months maximum. Best regards Paul On Wed, 26 Jan 2022 at 21:29, Jerry D via Fortran <fortran@gcc.gnu.org> wrote: > Is there any reason these patches can not be applied and use this test > as a test case? > > Regards, > > Jerry > > On 1/24/22 8:11 AM, Salvatore Filippone via Fortran wrote: > > Thanks a lot > > (yes, I suspected both gfortran and intel were wrong, precisely because I > > could see why you'd need two FINAL calls, but not three). > > > > Salvatore > > > > On Mon, Jan 24, 2022 at 4:45 PM Andrew Benson < > abenson@carnegiescience.edu> > > wrote: > > > >> Hi Salvatore, > >> > >> This looks like it's related to some of the missing finalization > >> functionality > >> (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37336). Paul has some > >> patches > >> (e.g. https://gcc.gnu.org/pipermail/fortran/2022-January/057415.html) > >> which > >> implement most of the missing functionality. With those patches > >> incorporated > >> your code gives the following output with gfortran: > >> > >> $ ./testfinal > >> Allocating wrapper > >> Calling new_outer_type > >> Assigning outer%test_item > >> Called delete_test_type > >> End of new_outer_type > >> DeAllocating wrapper > >> Called delete_test_type > >> > >> So there is one more call to the finalizer than you found - I haven't > >> checked > >> carefully but I would guess this is a deallocation of LHS on assignment. > >> > >> In testing these patches using the Intel compiler we found that it seems > >> to > >> call the finalization wrapper more than it should, sometimes on objects > >> that > >> have already been deallocated. Your code, compiled with the Intel > compiler > >> and > >> then run under valgrind shows the following: > >> > >> $ valgrind ./testfinal > >> ==7340== Memcheck, a memory error detector > >> ==7340== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. > >> ==7340== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright > info > >> ==7340== Command: ./testfinal > >> ==7340== > >> ==7340== Conditional jump or move depends on uninitialised value(s) > >> ==7340== at 0x493A51: __intel_sse2_strcpy (in > /home/abensonca/Scratch/ > >> ifortTests/testfinal) > >> ==7340== by 0x45D70E: for__add_to_lf_table (in > /home/abensonca/Scratch/ > >> ifortTests/testfinal) > >> ==7340== by 0x4410CB: for__open_proc (in /home/abensonca/Scratch/ > >> ifortTests/testfinal) > >> ==7340== by 0x423A64: for__open_default (in /home/abensonca/Scratch/ > >> ifortTests/testfinal) > >> ==7340== by 0x4305A9: for_write_seq_lis (in /home/abensonca/Scratch/ > >> ifortTests/testfinal) > >> ==7340== by 0x4047E1: MAIN__ (testfinal.f90:62) > >> ==7340== by 0x403CE1: main (in /home/abensonca/Scratch/ifortTests/ > >> testfinal) > >> ==7340== > >> Allocating wrapper > >> Calling new_outer_type > >> Assigning outer%test_item > >> Called delete_test_type > >> ==7340== Conditional jump or move depends on uninitialised value(s) > >> ==7340== at 0x40572A: do_alloc_copy (in > >> /home/abensonca/Scratch/ifortTests/ > >> testfinal) > >> ==7340== by 0x406B9A: do_alloc_copy (in > >> /home/abensonca/Scratch/ifortTests/ > >> testfinal) > >> ==7340== by 0x4084ED: for_alloc_assign_v2 (in > /home/abensonca/Scratch/ > >> ifortTests/testfinal) > >> ==7340== by 0x404474: target_mod_mp_new_outer_type_ > (testfinal.f90:48) > >> ==7340== by 0x40485E: MAIN__ (testfinal.f90:65) > >> ==7340== by 0x403CE1: main (in /home/abensonca/Scratch/ifortTests/ > >> testfinal) > >> ==7340== > >> Called delete_test_type > >> End of new_outer_type > >> DeAllocating wrapper > >> Called delete_test_type > >> ==7340== > >> ==7340== HEAP SUMMARY: > >> ==7340== in use at exit: 48 bytes in 1 blocks > >> ==7340== total heap usage: 14 allocs, 13 frees, 12,879 bytes allocated > >> ==7340== > >> ==7340== LEAK SUMMARY: > >> ==7340== definitely lost: 48 bytes in 1 blocks > >> ==7340== indirectly lost: 0 bytes in 0 blocks > >> ==7340== possibly lost: 0 bytes in 0 blocks > >> ==7340== still reachable: 0 bytes in 0 blocks > >> ==7340== suppressed: 0 bytes in 0 blocks > >> ==7340== Rerun with --leak-check=full to see details of leaked memory > >> ==7340== > >> ==7340== For counts of detected and suppressed errors, rerun with: -v > >> ==7340== Use --track-origins=yes to see where uninitialised values come > >> from > >> ==7340== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) > >> > >> so there are some cases of what look like incorrect accesses (and some > >> leaked > >> memory). > >> > >> Your code compiled with gfortran (with Paul's patches in place) shows > no > >> errors or leaks from valgrind. > >> > >> So, in summary, in this case I think the current gfortran is missing > some > >> finalizations (which are fixed by Paul's patches), and ifort is likely > >> doing > >> something wrong and probably calling the finalizer more times than it > >> should. > >> > >> -Andrew > >> > >> On Monday, January 24, 2022 6:49:23 AM PST Salvatore Filippone via > Fortran > >> wrote: > >>> And here is the code embedded as text............ sorry about sending > an > >>> attachment that was purged > >>> ------------------------- testfinal.f90 --------------------- > >>> module test_type_mod > >>> > >>> type :: my_test_type > >>> integer, allocatable :: i > >>> contains > >>> final :: delete_test_type > >>> end type my_test_type > >>> > >>> interface my_test_type > >>> module procedure new_test_type_object > >>> end interface my_test_type > >>> > >>> contains > >>> > >>> subroutine delete_test_type(this) > >>> type(my_test_type) :: this > >>> > >>> write(*,*) 'Called delete_test_type' > >>> if (allocated(this%i)) deallocate(this%i) > >>> > >>> end subroutine delete_test_type > >>> > >>> > >>> function new_test_type_object(item) result(res) > >>> type(my_test_type) :: res > >>> integer, intent(in) :: item > >>> !Allocation on assignment > >>> res%i=item > >>> end function new_test_type_object > >>> > >>> > >>> end module test_type_mod > >>> > >>> module target_mod > >>> use test_type_mod > >>> type :: outer_type > >>> type(my_test_type), allocatable :: test_item > >>> end type outer_type > >>> > >>> contains > >>> > >>> subroutine new_outer_type(outer,item) > >>> type(outer_type), intent(out) :: outer > >>> integer :: item > >>> > >>> allocate(outer%test_item) > >>> write(*,*) 'Assigning outer%test_item' > >>> outer%test_item = my_test_type(itemi) > >>> write(*,*) 'End of new_outer_type' > >>> end subroutine new_outer_type > >>> > >>> end module target_mod > >>> > >>> program testfinal > >>> use target_mod > >>> > >>> implicit none > >>> > >>> integer :: i=10 > >>> type(outer_type), allocatable :: wrapper > >>> > >>> write(*,*) 'Allocating wrapper ' > >>> allocate(wrapper) > >>> write(*,*) 'Calling new_outer_type ' > >>> call new_outer_type(wrapper,i) > >>> write(*,*) 'DeAllocating wrapper ' > >>> deallocate(wrapper) > >>> > >>> end program testfinal > >>> > >>> On Mon, Jan 24, 2022 at 2:50 PM Salvatore Filippone < > >>> > >>> filippone.salvatore@gmail.com> wrote: > >>>> Hi all > >>>> The attached code compiles and runs fine under both GNU and Intel, but > >> it > >>>> produces different results, in particular the FINAL subroutine is > >> invoked > >>>> just once with GNU, three times with Intel. > >>>> > >>>> It seems to me that they cannot both be right; I am not sure what the > >>>> standard is mandating in this case. > >>>> Any ideas? > >>>> Salvatore > >>>> --------------- Intel > >>>> [pr1eio03@login1: newstuff]$ ifort -v > >>>> ifort version 19.1.1.217 > >>>> [pr1eio03@login1: newstuff]$ ifort -o testfinal testfinal.f90 > >>>> [pr1eio03@login1: newstuff]$ ./testfinal > >>>> > >>>> Allocating wrapper > >>>> Calling new_outer_type > >>>> Assigning outer%test_item > >>>> Called delete_test_type > >>>> Called delete_test_type > >>>> End of new_outer_type > >>>> DeAllocating wrapper > >>>> Called delete_test_type > >>>> > >>>> ----------------------------- GNU > >>>> sfilippo@lagrange newstuff]$ gfortran -v > >>>> Using built-in specs. > >>>> COLLECT_GCC=gfortran > >>>> > COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/11/lto-wrapper > >>>> OFFLOAD_TARGET_NAMES=nvptx-none > >>>> OFFLOAD_TARGET_DEFAULT=1 > >>>> Target: x86_64-redhat-linux > >>>> Configured with: ../configure --enable-bootstrap > >>>> --enable-languages=c,c++,fortran,objc,obj-c++,ada,go,d,lto > >> --prefix=/usr > >>>> --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl= > >>>> http://bugzilla.redhat.com/bugzilla --enable-shared > >>>> --enable-threads=posix --enable-checking=release --enable-multilib > >>>> --with-system-zlib --enable-__cxa_atexit > --disable-libunwind-exceptions > >>>> --enable-gnu-unique-object --enable-linker-build-id > >>>> --with-gcc-major-version-only --with-linker-hash-style=gnu > >> --enable-plugin > >>>> --enable-initfini-array > >>>> > >> > --with-isl=/builddir/build/BUILD/gcc-11.2.1-20210728/obj-x86_64-redhat-lin > >>>> ux/isl-install --enable-offload-targets=nvptx-none > >> --without-cuda-driver > >>>> --enable-gnu-indirect-function --enable-cet --with-tune=generic > >>>> --with-arch_32=i686 --build=x86_64-redhat-linux > >>>> Thread model: posix > >>>> Supported LTO compression algorithms: zlib zstd > >>>> gcc version 11.2.1 20210728 (Red Hat 11.2.1-1) (GCC) > >>>> [sfilippo@lagrange newstuff]$ gfortran -o testfinal testfinal.f90 > >>>> [sfilippo@lagrange newstuff]$ ./testfinal > >>>> > >>>> Allocating wrapper > >>>> Calling new_outer_type > >>>> Assigning outer%test_item > >>>> End of new_outer_type > >>>> DeAllocating wrapper > >>>> Called delete_test_type > >>>> > >>>> --------------------- > >> > >> -- > >> > >> * Andrew Benson: https://abensonca.github.io > >> > >> * Galacticus: https://github.com/galacticusorg/galacticus > >> > >> > >> > >> > > -- "If you can't explain it simply, you don't understand it well enough" - Albert Einstein ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: FINAL subroutines 2022-01-26 22:59 ` Paul Richard Thomas @ 2022-01-27 7:17 ` Salvatore Filippone 2022-01-27 22:10 ` Paul Richard Thomas 0 siblings, 1 reply; 10+ messages in thread From: Salvatore Filippone @ 2022-01-27 7:17 UTC (permalink / raw) To: Paul Richard Thomas; +Cc: Jerry D, Andrew Benson, Damian Rouson, Fortran List One more data point: Cray FTN issues TWO calls to the FINAL. Which begs the question: what is the correct number of calls one, two or three? Salvatore fsalvato@daint102:/project/prce01/fsalvato/NUMERICAL/PSBLAS/V4/psblas4/test/newstuff> ftn --version Cray Fortran : Version 11.0.0 fsalvato@daint102:/project/prce01/fsalvato/NUMERICAL/PSBLAS/V4/psblas4/test/newstuff> ftn -o testfinal testfinal.f90 fsalvato@daint102:/project/prce01/fsalvato/NUMERICAL/PSBLAS/V4/psblas4/test/newstuff> ./testfinal Allocating wrapper Calling new_outer_type Assigning outer%test_item Called delete_test_type End of new_outer_type DeAllocating wrapper Called delete_test_type On Wed, Jan 26, 2022 at 11:59 PM Paul Richard Thomas < paul.richard.thomas@gmail.com> wrote: > Hi Jerry, > > I am trying to fix the failure of my latest patch with this very test > case. Otherwise it fixes most of the remaining dependencies in PR37336. > > At a pinch, I could submit the earlier patch that Andrew mentions and work > from there. However, you will note that it does miss one of the > finalizations. This is critical because function results, which should be > finalized, are not. > > I'll keep an eye on the state of the branch. By and large, release occurs > 3-4 months after the start of stage 4. I will leave 2 months maximum. > > Best regards > > Paul > > > On Wed, 26 Jan 2022 at 21:29, Jerry D via Fortran <fortran@gcc.gnu.org> > wrote: > >> Is there any reason these patches can not be applied and use this test >> as a test case? >> >> Regards, >> >> Jerry >> >> On 1/24/22 8:11 AM, Salvatore Filippone via Fortran wrote: >> > Thanks a lot >> > (yes, I suspected both gfortran and intel were wrong, precisely because >> I >> > could see why you'd need two FINAL calls, but not three). >> > >> > Salvatore >> > >> > On Mon, Jan 24, 2022 at 4:45 PM Andrew Benson < >> abenson@carnegiescience.edu> >> > wrote: >> > >> >> Hi Salvatore, >> >> >> >> This looks like it's related to some of the missing finalization >> >> functionality >> >> (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37336). Paul has some >> >> patches >> >> (e.g. https://gcc.gnu.org/pipermail/fortran/2022-January/057415.html) >> >> which >> >> implement most of the missing functionality. With those patches >> >> incorporated >> >> your code gives the following output with gfortran: >> >> >> >> $ ./testfinal >> >> Allocating wrapper >> >> Calling new_outer_type >> >> Assigning outer%test_item >> >> Called delete_test_type >> >> End of new_outer_type >> >> DeAllocating wrapper >> >> Called delete_test_type >> >> >> >> So there is one more call to the finalizer than you found - I haven't >> >> checked >> >> carefully but I would guess this is a deallocation of LHS on >> assignment. >> >> >> >> In testing these patches using the Intel compiler we found that it >> seems >> >> to >> >> call the finalization wrapper more than it should, sometimes on objects >> >> that >> >> have already been deallocated. Your code, compiled with the Intel >> compiler >> >> and >> >> then run under valgrind shows the following: >> >> >> >> $ valgrind ./testfinal >> >> ==7340== Memcheck, a memory error detector >> >> ==7340== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et >> al. >> >> ==7340== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright >> info >> >> ==7340== Command: ./testfinal >> >> ==7340== >> >> ==7340== Conditional jump or move depends on uninitialised value(s) >> >> ==7340== at 0x493A51: __intel_sse2_strcpy (in >> /home/abensonca/Scratch/ >> >> ifortTests/testfinal) >> >> ==7340== by 0x45D70E: for__add_to_lf_table (in >> /home/abensonca/Scratch/ >> >> ifortTests/testfinal) >> >> ==7340== by 0x4410CB: for__open_proc (in /home/abensonca/Scratch/ >> >> ifortTests/testfinal) >> >> ==7340== by 0x423A64: for__open_default (in /home/abensonca/Scratch/ >> >> ifortTests/testfinal) >> >> ==7340== by 0x4305A9: for_write_seq_lis (in /home/abensonca/Scratch/ >> >> ifortTests/testfinal) >> >> ==7340== by 0x4047E1: MAIN__ (testfinal.f90:62) >> >> ==7340== by 0x403CE1: main (in /home/abensonca/Scratch/ifortTests/ >> >> testfinal) >> >> ==7340== >> >> Allocating wrapper >> >> Calling new_outer_type >> >> Assigning outer%test_item >> >> Called delete_test_type >> >> ==7340== Conditional jump or move depends on uninitialised value(s) >> >> ==7340== at 0x40572A: do_alloc_copy (in >> >> /home/abensonca/Scratch/ifortTests/ >> >> testfinal) >> >> ==7340== by 0x406B9A: do_alloc_copy (in >> >> /home/abensonca/Scratch/ifortTests/ >> >> testfinal) >> >> ==7340== by 0x4084ED: for_alloc_assign_v2 (in >> /home/abensonca/Scratch/ >> >> ifortTests/testfinal) >> >> ==7340== by 0x404474: target_mod_mp_new_outer_type_ >> (testfinal.f90:48) >> >> ==7340== by 0x40485E: MAIN__ (testfinal.f90:65) >> >> ==7340== by 0x403CE1: main (in /home/abensonca/Scratch/ifortTests/ >> >> testfinal) >> >> ==7340== >> >> Called delete_test_type >> >> End of new_outer_type >> >> DeAllocating wrapper >> >> Called delete_test_type >> >> ==7340== >> >> ==7340== HEAP SUMMARY: >> >> ==7340== in use at exit: 48 bytes in 1 blocks >> >> ==7340== total heap usage: 14 allocs, 13 frees, 12,879 bytes >> allocated >> >> ==7340== >> >> ==7340== LEAK SUMMARY: >> >> ==7340== definitely lost: 48 bytes in 1 blocks >> >> ==7340== indirectly lost: 0 bytes in 0 blocks >> >> ==7340== possibly lost: 0 bytes in 0 blocks >> >> ==7340== still reachable: 0 bytes in 0 blocks >> >> ==7340== suppressed: 0 bytes in 0 blocks >> >> ==7340== Rerun with --leak-check=full to see details of leaked memory >> >> ==7340== >> >> ==7340== For counts of detected and suppressed errors, rerun with: -v >> >> ==7340== Use --track-origins=yes to see where uninitialised values come >> >> from >> >> ==7340== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) >> >> >> >> so there are some cases of what look like incorrect accesses (and some >> >> leaked >> >> memory). >> >> >> >> Your code compiled with gfortran (with Paul's patches in place) shows >> no >> >> errors or leaks from valgrind. >> >> >> >> So, in summary, in this case I think the current gfortran is missing >> some >> >> finalizations (which are fixed by Paul's patches), and ifort is likely >> >> doing >> >> something wrong and probably calling the finalizer more times than it >> >> should. >> >> >> >> -Andrew >> >> >> >> On Monday, January 24, 2022 6:49:23 AM PST Salvatore Filippone via >> Fortran >> >> wrote: >> >>> And here is the code embedded as text............ sorry about >> sending an >> >>> attachment that was purged >> >>> ------------------------- testfinal.f90 --------------------- >> >>> module test_type_mod >> >>> >> >>> type :: my_test_type >> >>> integer, allocatable :: i >> >>> contains >> >>> final :: delete_test_type >> >>> end type my_test_type >> >>> >> >>> interface my_test_type >> >>> module procedure new_test_type_object >> >>> end interface my_test_type >> >>> >> >>> contains >> >>> >> >>> subroutine delete_test_type(this) >> >>> type(my_test_type) :: this >> >>> >> >>> write(*,*) 'Called delete_test_type' >> >>> if (allocated(this%i)) deallocate(this%i) >> >>> >> >>> end subroutine delete_test_type >> >>> >> >>> >> >>> function new_test_type_object(item) result(res) >> >>> type(my_test_type) :: res >> >>> integer, intent(in) :: item >> >>> !Allocation on assignment >> >>> res%i=item >> >>> end function new_test_type_object >> >>> >> >>> >> >>> end module test_type_mod >> >>> >> >>> module target_mod >> >>> use test_type_mod >> >>> type :: outer_type >> >>> type(my_test_type), allocatable :: test_item >> >>> end type outer_type >> >>> >> >>> contains >> >>> >> >>> subroutine new_outer_type(outer,item) >> >>> type(outer_type), intent(out) :: outer >> >>> integer :: item >> >>> >> >>> allocate(outer%test_item) >> >>> write(*,*) 'Assigning outer%test_item' >> >>> outer%test_item = my_test_type(itemi) >> >>> write(*,*) 'End of new_outer_type' >> >>> end subroutine new_outer_type >> >>> >> >>> end module target_mod >> >>> >> >>> program testfinal >> >>> use target_mod >> >>> >> >>> implicit none >> >>> >> >>> integer :: i=10 >> >>> type(outer_type), allocatable :: wrapper >> >>> >> >>> write(*,*) 'Allocating wrapper ' >> >>> allocate(wrapper) >> >>> write(*,*) 'Calling new_outer_type ' >> >>> call new_outer_type(wrapper,i) >> >>> write(*,*) 'DeAllocating wrapper ' >> >>> deallocate(wrapper) >> >>> >> >>> end program testfinal >> >>> >> >>> On Mon, Jan 24, 2022 at 2:50 PM Salvatore Filippone < >> >>> >> >>> filippone.salvatore@gmail.com> wrote: >> >>>> Hi all >> >>>> The attached code compiles and runs fine under both GNU and Intel, >> but >> >> it >> >>>> produces different results, in particular the FINAL subroutine is >> >> invoked >> >>>> just once with GNU, three times with Intel. >> >>>> >> >>>> It seems to me that they cannot both be right; I am not sure what the >> >>>> standard is mandating in this case. >> >>>> Any ideas? >> >>>> Salvatore >> >>>> --------------- Intel >> >>>> [pr1eio03@login1: newstuff]$ ifort -v >> >>>> ifort version 19.1.1.217 >> >>>> [pr1eio03@login1: newstuff]$ ifort -o testfinal testfinal.f90 >> >>>> [pr1eio03@login1: newstuff]$ ./testfinal >> >>>> >> >>>> Allocating wrapper >> >>>> Calling new_outer_type >> >>>> Assigning outer%test_item >> >>>> Called delete_test_type >> >>>> Called delete_test_type >> >>>> End of new_outer_type >> >>>> DeAllocating wrapper >> >>>> Called delete_test_type >> >>>> >> >>>> ----------------------------- GNU >> >>>> sfilippo@lagrange newstuff]$ gfortran -v >> >>>> Using built-in specs. >> >>>> COLLECT_GCC=gfortran >> >>>> >> COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/11/lto-wrapper >> >>>> OFFLOAD_TARGET_NAMES=nvptx-none >> >>>> OFFLOAD_TARGET_DEFAULT=1 >> >>>> Target: x86_64-redhat-linux >> >>>> Configured with: ../configure --enable-bootstrap >> >>>> --enable-languages=c,c++,fortran,objc,obj-c++,ada,go,d,lto >> >> --prefix=/usr >> >>>> --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl= >> >>>> http://bugzilla.redhat.com/bugzilla --enable-shared >> >>>> --enable-threads=posix --enable-checking=release --enable-multilib >> >>>> --with-system-zlib --enable-__cxa_atexit >> --disable-libunwind-exceptions >> >>>> --enable-gnu-unique-object --enable-linker-build-id >> >>>> --with-gcc-major-version-only --with-linker-hash-style=gnu >> >> --enable-plugin >> >>>> --enable-initfini-array >> >>>> >> >> >> --with-isl=/builddir/build/BUILD/gcc-11.2.1-20210728/obj-x86_64-redhat-lin >> >>>> ux/isl-install --enable-offload-targets=nvptx-none >> >> --without-cuda-driver >> >>>> --enable-gnu-indirect-function --enable-cet --with-tune=generic >> >>>> --with-arch_32=i686 --build=x86_64-redhat-linux >> >>>> Thread model: posix >> >>>> Supported LTO compression algorithms: zlib zstd >> >>>> gcc version 11.2.1 20210728 (Red Hat 11.2.1-1) (GCC) >> >>>> [sfilippo@lagrange newstuff]$ gfortran -o testfinal testfinal.f90 >> >>>> [sfilippo@lagrange newstuff]$ ./testfinal >> >>>> >> >>>> Allocating wrapper >> >>>> Calling new_outer_type >> >>>> Assigning outer%test_item >> >>>> End of new_outer_type >> >>>> DeAllocating wrapper >> >>>> Called delete_test_type >> >>>> >> >>>> --------------------- >> >> >> >> -- >> >> >> >> * Andrew Benson: https://abensonca.github.io >> >> >> >> * Galacticus: https://github.com/galacticusorg/galacticus >> >> >> >> >> >> >> >> >> >> > > -- > "If you can't explain it simply, you don't understand it well enough" - > Albert Einstein > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: FINAL subroutines 2022-01-27 7:17 ` Salvatore Filippone @ 2022-01-27 22:10 ` Paul Richard Thomas 2022-01-28 8:05 ` Salvatore Filippone 0 siblings, 1 reply; 10+ messages in thread From: Paul Richard Thomas @ 2022-01-27 22:10 UTC (permalink / raw) To: Salvatore Filippone; +Cc: Jerry D, Andrew Benson, Damian Rouson, Fortran List [-- Attachment #1: Type: text/plain, Size: 13270 bytes --] Hi Salvatore, My reading of F2018: 7.5.6.3 "When finalization occurs" is that three calls is correct. (i) Paragraph 1 stipulates that the 'var' expression be evaluated before the reallocation and intrinsic assignment; (ii)stipulates that the function result be finalised "the result is finalized after execution of the innermost executable construct containing the reference." ; and (iii) Finalisation occurs on going out of scope. That is what is implemented in the attached. I am working my way through the testcase dependencies of PR37336 making sure that finalizat ion occurs as required by 7.5.6.3 and in the order defined in the previous section. It will all be done in the next few days. What will remain is finalization of function results within array constructors and one or two other corner cases. Following that, the existing finalization calls will be brought into the framework as the new calls. Best regards Paul On Thu, 27 Jan 2022 at 07:17, Salvatore Filippone < filippone.salvatore@gmail.com> wrote: > One more data point: Cray FTN issues TWO calls to the FINAL. > Which begs the question: what is the correct number of calls one, two or > three? > Salvatore > > fsalvato@daint102:/project/prce01/fsalvato/NUMERICAL/PSBLAS/V4/psblas4/test/newstuff> > ftn --version > Cray Fortran : Version 11.0.0 > fsalvato@daint102:/project/prce01/fsalvato/NUMERICAL/PSBLAS/V4/psblas4/test/newstuff> > ftn -o testfinal testfinal.f90 > fsalvato@daint102:/project/prce01/fsalvato/NUMERICAL/PSBLAS/V4/psblas4/test/newstuff> > ./testfinal > Allocating wrapper > Calling new_outer_type > Assigning outer%test_item > Called delete_test_type > End of new_outer_type > DeAllocating wrapper > Called delete_test_type > > On Wed, Jan 26, 2022 at 11:59 PM Paul Richard Thomas < > paul.richard.thomas@gmail.com> wrote: > >> Hi Jerry, >> >> I am trying to fix the failure of my latest patch with this very test >> case. Otherwise it fixes most of the remaining dependencies in PR37336. >> >> At a pinch, I could submit the earlier patch that Andrew mentions and >> work from there. However, you will note that it does miss one of the >> finalizations. This is critical because function results, which should be >> finalized, are not. >> >> I'll keep an eye on the state of the branch. By and large, release occurs >> 3-4 months after the start of stage 4. I will leave 2 months maximum. >> >> Best regards >> >> Paul >> >> >> On Wed, 26 Jan 2022 at 21:29, Jerry D via Fortran <fortran@gcc.gnu.org> >> wrote: >> >>> Is there any reason these patches can not be applied and use this test >>> as a test case? >>> >>> Regards, >>> >>> Jerry >>> >>> On 1/24/22 8:11 AM, Salvatore Filippone via Fortran wrote: >>> > Thanks a lot >>> > (yes, I suspected both gfortran and intel were wrong, precisely >>> because I >>> > could see why you'd need two FINAL calls, but not three). >>> > >>> > Salvatore >>> > >>> > On Mon, Jan 24, 2022 at 4:45 PM Andrew Benson < >>> abenson@carnegiescience.edu> >>> > wrote: >>> > >>> >> Hi Salvatore, >>> >> >>> >> This looks like it's related to some of the missing finalization >>> >> functionality >>> >> (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37336). Paul has some >>> >> patches >>> >> (e.g. https://gcc.gnu.org/pipermail/fortran/2022-January/057415.html) >>> >> which >>> >> implement most of the missing functionality. With those patches >>> >> incorporated >>> >> your code gives the following output with gfortran: >>> >> >>> >> $ ./testfinal >>> >> Allocating wrapper >>> >> Calling new_outer_type >>> >> Assigning outer%test_item >>> >> Called delete_test_type >>> >> End of new_outer_type >>> >> DeAllocating wrapper >>> >> Called delete_test_type >>> >> >>> >> So there is one more call to the finalizer than you found - I haven't >>> >> checked >>> >> carefully but I would guess this is a deallocation of LHS on >>> assignment. >>> >> >>> >> In testing these patches using the Intel compiler we found that it >>> seems >>> >> to >>> >> call the finalization wrapper more than it should, sometimes on >>> objects >>> >> that >>> >> have already been deallocated. Your code, compiled with the Intel >>> compiler >>> >> and >>> >> then run under valgrind shows the following: >>> >> >>> >> $ valgrind ./testfinal >>> >> ==7340== Memcheck, a memory error detector >>> >> ==7340== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et >>> al. >>> >> ==7340== Using Valgrind-3.13.0 and LibVEX; rerun with -h for >>> copyright info >>> >> ==7340== Command: ./testfinal >>> >> ==7340== >>> >> ==7340== Conditional jump or move depends on uninitialised value(s) >>> >> ==7340== at 0x493A51: __intel_sse2_strcpy (in >>> /home/abensonca/Scratch/ >>> >> ifortTests/testfinal) >>> >> ==7340== by 0x45D70E: for__add_to_lf_table (in >>> /home/abensonca/Scratch/ >>> >> ifortTests/testfinal) >>> >> ==7340== by 0x4410CB: for__open_proc (in /home/abensonca/Scratch/ >>> >> ifortTests/testfinal) >>> >> ==7340== by 0x423A64: for__open_default (in >>> /home/abensonca/Scratch/ >>> >> ifortTests/testfinal) >>> >> ==7340== by 0x4305A9: for_write_seq_lis (in >>> /home/abensonca/Scratch/ >>> >> ifortTests/testfinal) >>> >> ==7340== by 0x4047E1: MAIN__ (testfinal.f90:62) >>> >> ==7340== by 0x403CE1: main (in /home/abensonca/Scratch/ifortTests/ >>> >> testfinal) >>> >> ==7340== >>> >> Allocating wrapper >>> >> Calling new_outer_type >>> >> Assigning outer%test_item >>> >> Called delete_test_type >>> >> ==7340== Conditional jump or move depends on uninitialised value(s) >>> >> ==7340== at 0x40572A: do_alloc_copy (in >>> >> /home/abensonca/Scratch/ifortTests/ >>> >> testfinal) >>> >> ==7340== by 0x406B9A: do_alloc_copy (in >>> >> /home/abensonca/Scratch/ifortTests/ >>> >> testfinal) >>> >> ==7340== by 0x4084ED: for_alloc_assign_v2 (in >>> /home/abensonca/Scratch/ >>> >> ifortTests/testfinal) >>> >> ==7340== by 0x404474: target_mod_mp_new_outer_type_ >>> (testfinal.f90:48) >>> >> ==7340== by 0x40485E: MAIN__ (testfinal.f90:65) >>> >> ==7340== by 0x403CE1: main (in /home/abensonca/Scratch/ifortTests/ >>> >> testfinal) >>> >> ==7340== >>> >> Called delete_test_type >>> >> End of new_outer_type >>> >> DeAllocating wrapper >>> >> Called delete_test_type >>> >> ==7340== >>> >> ==7340== HEAP SUMMARY: >>> >> ==7340== in use at exit: 48 bytes in 1 blocks >>> >> ==7340== total heap usage: 14 allocs, 13 frees, 12,879 bytes >>> allocated >>> >> ==7340== >>> >> ==7340== LEAK SUMMARY: >>> >> ==7340== definitely lost: 48 bytes in 1 blocks >>> >> ==7340== indirectly lost: 0 bytes in 0 blocks >>> >> ==7340== possibly lost: 0 bytes in 0 blocks >>> >> ==7340== still reachable: 0 bytes in 0 blocks >>> >> ==7340== suppressed: 0 bytes in 0 blocks >>> >> ==7340== Rerun with --leak-check=full to see details of leaked memory >>> >> ==7340== >>> >> ==7340== For counts of detected and suppressed errors, rerun with: -v >>> >> ==7340== Use --track-origins=yes to see where uninitialised values >>> come >>> >> from >>> >> ==7340== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from >>> 0) >>> >> >>> >> so there are some cases of what look like incorrect accesses (and some >>> >> leaked >>> >> memory). >>> >> >>> >> Your code compiled with gfortran (with Paul's patches in place) >>> shows no >>> >> errors or leaks from valgrind. >>> >> >>> >> So, in summary, in this case I think the current gfortran is missing >>> some >>> >> finalizations (which are fixed by Paul's patches), and ifort is likely >>> >> doing >>> >> something wrong and probably calling the finalizer more times than it >>> >> should. >>> >> >>> >> -Andrew >>> >> >>> >> On Monday, January 24, 2022 6:49:23 AM PST Salvatore Filippone via >>> Fortran >>> >> wrote: >>> >>> And here is the code embedded as text............ sorry about >>> sending an >>> >>> attachment that was purged >>> >>> ------------------------- testfinal.f90 --------------------- >>> >>> module test_type_mod >>> >>> >>> >>> type :: my_test_type >>> >>> integer, allocatable :: i >>> >>> contains >>> >>> final :: delete_test_type >>> >>> end type my_test_type >>> >>> >>> >>> interface my_test_type >>> >>> module procedure new_test_type_object >>> >>> end interface my_test_type >>> >>> >>> >>> contains >>> >>> >>> >>> subroutine delete_test_type(this) >>> >>> type(my_test_type) :: this >>> >>> >>> >>> write(*,*) 'Called delete_test_type' >>> >>> if (allocated(this%i)) deallocate(this%i) >>> >>> >>> >>> end subroutine delete_test_type >>> >>> >>> >>> >>> >>> function new_test_type_object(item) result(res) >>> >>> type(my_test_type) :: res >>> >>> integer, intent(in) :: item >>> >>> !Allocation on assignment >>> >>> res%i=item >>> >>> end function new_test_type_object >>> >>> >>> >>> >>> >>> end module test_type_mod >>> >>> >>> >>> module target_mod >>> >>> use test_type_mod >>> >>> type :: outer_type >>> >>> type(my_test_type), allocatable :: test_item >>> >>> end type outer_type >>> >>> >>> >>> contains >>> >>> >>> >>> subroutine new_outer_type(outer,item) >>> >>> type(outer_type), intent(out) :: outer >>> >>> integer :: item >>> >>> >>> >>> allocate(outer%test_item) >>> >>> write(*,*) 'Assigning outer%test_item' >>> >>> outer%test_item = my_test_type(itemi) >>> >>> write(*,*) 'End of new_outer_type' >>> >>> end subroutine new_outer_type >>> >>> >>> >>> end module target_mod >>> >>> >>> >>> program testfinal >>> >>> use target_mod >>> >>> >>> >>> implicit none >>> >>> >>> >>> integer :: i=10 >>> >>> type(outer_type), allocatable :: wrapper >>> >>> >>> >>> write(*,*) 'Allocating wrapper ' >>> >>> allocate(wrapper) >>> >>> write(*,*) 'Calling new_outer_type ' >>> >>> call new_outer_type(wrapper,i) >>> >>> write(*,*) 'DeAllocating wrapper ' >>> >>> deallocate(wrapper) >>> >>> >>> >>> end program testfinal >>> >>> >>> >>> On Mon, Jan 24, 2022 at 2:50 PM Salvatore Filippone < >>> >>> >>> >>> filippone.salvatore@gmail.com> wrote: >>> >>>> Hi all >>> >>>> The attached code compiles and runs fine under both GNU and Intel, >>> but >>> >> it >>> >>>> produces different results, in particular the FINAL subroutine is >>> >> invoked >>> >>>> just once with GNU, three times with Intel. >>> >>>> >>> >>>> It seems to me that they cannot both be right; I am not sure what >>> the >>> >>>> standard is mandating in this case. >>> >>>> Any ideas? >>> >>>> Salvatore >>> >>>> --------------- Intel >>> >>>> [pr1eio03@login1: newstuff]$ ifort -v >>> >>>> ifort version 19.1.1.217 >>> >>>> [pr1eio03@login1: newstuff]$ ifort -o testfinal testfinal.f90 >>> >>>> [pr1eio03@login1: newstuff]$ ./testfinal >>> >>>> >>> >>>> Allocating wrapper >>> >>>> Calling new_outer_type >>> >>>> Assigning outer%test_item >>> >>>> Called delete_test_type >>> >>>> Called delete_test_type >>> >>>> End of new_outer_type >>> >>>> DeAllocating wrapper >>> >>>> Called delete_test_type >>> >>>> >>> >>>> ----------------------------- GNU >>> >>>> sfilippo@lagrange newstuff]$ gfortran -v >>> >>>> Using built-in specs. >>> >>>> COLLECT_GCC=gfortran >>> >>>> >>> COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/11/lto-wrapper >>> >>>> OFFLOAD_TARGET_NAMES=nvptx-none >>> >>>> OFFLOAD_TARGET_DEFAULT=1 >>> >>>> Target: x86_64-redhat-linux >>> >>>> Configured with: ../configure --enable-bootstrap >>> >>>> --enable-languages=c,c++,fortran,objc,obj-c++,ada,go,d,lto >>> >> --prefix=/usr >>> >>>> --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl= >>> >>>> http://bugzilla.redhat.com/bugzilla --enable-shared >>> >>>> --enable-threads=posix --enable-checking=release --enable-multilib >>> >>>> --with-system-zlib --enable-__cxa_atexit >>> --disable-libunwind-exceptions >>> >>>> --enable-gnu-unique-object --enable-linker-build-id >>> >>>> --with-gcc-major-version-only --with-linker-hash-style=gnu >>> >> --enable-plugin >>> >>>> --enable-initfini-array >>> >>>> >>> >> >>> --with-isl=/builddir/build/BUILD/gcc-11.2.1-20210728/obj-x86_64-redhat-lin >>> >>>> ux/isl-install --enable-offload-targets=nvptx-none >>> >> --without-cuda-driver >>> >>>> --enable-gnu-indirect-function --enable-cet --with-tune=generic >>> >>>> --with-arch_32=i686 --build=x86_64-redhat-linux >>> >>>> Thread model: posix >>> >>>> Supported LTO compression algorithms: zlib zstd >>> >>>> gcc version 11.2.1 20210728 (Red Hat 11.2.1-1) (GCC) >>> >>>> [sfilippo@lagrange newstuff]$ gfortran -o testfinal testfinal.f90 >>> >>>> [sfilippo@lagrange newstuff]$ ./testfinal >>> >>>> >>> >>>> Allocating wrapper >>> >>>> Calling new_outer_type >>> >>>> Assigning outer%test_item >>> >>>> End of new_outer_type >>> >>>> DeAllocating wrapper >>> >>>> Called delete_test_type >>> >>>> >>> >>>> --------------------- >>> >> >>> >> -- >>> >> >>> >> * Andrew Benson: https://abensonca.github.io >>> >> >>> >> * Galacticus: https://github.com/galacticusorg/galacticus >>> >> >>> >> >>> >> >>> >> >>> >>> >> >> -- >> "If you can't explain it simply, you don't understand it well enough" - >> Albert Einstein >> > -- "If you can't explain it simply, you don't understand it well enough" - Albert Einstein [-- Attachment #2: Check270222.diff --] [-- Type: text/x-patch, Size: 34670 bytes --] diff --git a/gcc/fortran/class.cc b/gcc/fortran/class.cc index 731e9b0fe6a..a249eea4a30 100644 --- a/gcc/fortran/class.cc +++ b/gcc/fortran/class.cc @@ -896,7 +896,8 @@ has_finalizer_component (gfc_symbol *derived) gfc_component *c; for (c = derived->components; c; c = c->next) - if (c->ts.type == BT_DERIVED && !c->attr.pointer && !c->attr.allocatable) + if (c->ts.type == BT_DERIVED && !c->attr.pointer && !c->attr.allocatable + && c->attr.flavor != FL_PROCEDURE) { if (c->ts.u.derived->f2k_derived && c->ts.u.derived->f2k_derived->finalizers) @@ -1059,7 +1060,8 @@ finalize_component (gfc_expr *expr, gfc_symbol *derived, gfc_component *comp, { /* Call FINAL_WRAPPER (comp); */ gfc_code *final_wrap; - gfc_symbol *vtab; + gfc_symbol *vtab, *byte_stride; + gfc_expr *scalar, *size_expr, *fini_coarray_expr; gfc_component *c; vtab = gfc_find_derived_vtab (comp->ts.u.derived); @@ -1068,12 +1070,54 @@ finalize_component (gfc_expr *expr, gfc_symbol *derived, gfc_component *comp, break; gcc_assert (c); + + /* Set scalar argument for storage_size. */ + gfc_get_symbol ("comp_byte_stride", sub_ns, &byte_stride); + byte_stride->ts = e->ts; + byte_stride->attr.flavor = FL_VARIABLE; + byte_stride->attr.value = 1; + byte_stride->attr.artificial = 1; + gfc_set_sym_referenced (byte_stride); + gfc_commit_symbol (byte_stride); + scalar = gfc_lval_expr_from_sym (byte_stride); + final_wrap = gfc_get_code (EXEC_CALL); final_wrap->symtree = c->initializer->symtree; final_wrap->resolved_sym = c->initializer->symtree->n.sym; final_wrap->ext.actual = gfc_get_actual_arglist (); final_wrap->ext.actual->expr = e; + /* size_expr = STORAGE_SIZE (...) / NUMERIC_STORAGE_SIZE. */ + size_expr = gfc_get_expr (); + size_expr->where = gfc_current_locus; + size_expr->expr_type = EXPR_OP; + size_expr->value.op.op = INTRINSIC_DIVIDE; + + /* STORAGE_SIZE (array,kind=c_intptr_t). */ + size_expr->value.op.op1 + = gfc_build_intrinsic_call (sub_ns, GFC_ISYM_STORAGE_SIZE, + "storage_size", gfc_current_locus, 2, + scalar, + gfc_get_int_expr (gfc_index_integer_kind, + NULL, 0)); + + /* NUMERIC_STORAGE_SIZE. */ + size_expr->value.op.op2 = gfc_get_int_expr (gfc_index_integer_kind, NULL, + gfc_character_storage_size); + size_expr->value.op.op1->ts = size_expr->value.op.op2->ts; + size_expr->ts = size_expr->value.op.op1->ts; + + /* Which provides the argument 'byte_stride'..... */ + final_wrap->ext.actual->next = gfc_get_actual_arglist (); + final_wrap->ext.actual->next->expr = size_expr; + + /* ...and last of all the 'fini_coarray' argument. */ + fini_coarray_expr = gfc_lval_expr_from_sym (fini_coarray); + final_wrap->ext.actual->next->next = gfc_get_actual_arglist (); + final_wrap->ext.actual->next->next->expr = fini_coarray_expr; + + + if (*code) { (*code)->next = final_wrap; @@ -1430,8 +1474,6 @@ finalizer_insert_packed_call (gfc_code *block, gfc_finalizer *fini, block->next->resolved_sym = fini->proc_tree->n.sym; block->next->ext.actual = gfc_get_actual_arglist (); block->next->ext.actual->expr = gfc_lval_expr_from_sym (array); - block->next->ext.actual->next = gfc_get_actual_arglist (); - block->next->ext.actual->next->expr = gfc_copy_expr (size_expr); /* ELSE. */ diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc index 835a4783718..5558af4e2ba 100644 --- a/gcc/fortran/resolve.cc +++ b/gcc/fortran/resolve.cc @@ -10512,6 +10512,10 @@ resolve_where (gfc_code *code, gfc_expr *mask) if (e && !resolve_where_shape (cnext->expr1, e)) gfc_error ("WHERE assignment target at %L has " "inconsistent shape", &cnext->expr1->where); + + if (cnext->op == EXEC_ASSIGN) + cnext->expr1->must_finalize = 1; + break; @@ -10599,6 +10603,10 @@ gfc_resolve_where_code_in_forall (gfc_code *code, int nvar, /* WHERE assignment statement */ case EXEC_ASSIGN: gfc_resolve_assign_in_forall (cnext, nvar, var_expr); + + if (cnext->op == EXEC_ASSIGN) + cnext->expr1->must_finalize = 1; + break; /* WHERE operator assignment statement */ @@ -10645,6 +10653,10 @@ gfc_resolve_forall_body (gfc_code *code, int nvar, gfc_expr **var_expr) case EXEC_ASSIGN: case EXEC_POINTER_ASSIGN: gfc_resolve_assign_in_forall (c, nvar, var_expr); + + if (c->op == EXEC_ASSIGN) + c->expr1->must_finalize = 1; + break; case EXEC_ASSIGN_CALL: @@ -12069,6 +12081,9 @@ start: && code->expr1->ts.u.derived->attr.defined_assign_comp) generate_component_assignments (&code, ns); + if (code->op == EXEC_ASSIGN) + code->expr1->must_finalize = 1; + break; case EXEC_LABEL_ASSIGN: diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc index 2f0c8a4d412..b03e74960ce 100644 --- a/gcc/fortran/trans-array.cc +++ b/gcc/fortran/trans-array.cc @@ -994,9 +994,9 @@ gfc_get_array_span (tree desc, gfc_expr *expr) if (tmp && TREE_CODE (tmp) == ARRAY_TYPE && TYPE_STRING_FLAG (tmp)) { gcc_assert (expr->ts.type == BT_CHARACTER); - + tmp = gfc_get_character_len_in_bytes (tmp); - + if (tmp == NULL_TREE || integer_zerop (tmp)) { tree bs; @@ -1007,7 +1007,7 @@ gfc_get_array_span (tree desc, gfc_expr *expr) tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type, tmp, bs); } - + tmp = (tmp && !integer_zerop (tmp)) ? (fold_convert (gfc_array_index_type, tmp)) : (NULL_TREE); } @@ -5657,7 +5657,12 @@ gfc_array_init_size (tree descriptor, int rank, int corank, tree * poffset, gfc_se se; int n; - type = TREE_TYPE (descriptor); + if (expr->ts.type == BT_CLASS + && expr3_desc != NULL_TREE + && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (expr3_desc))) + type = TREE_TYPE (expr3_desc); + else + type = TREE_TYPE (descriptor); stride = gfc_index_one_node; offset = gfc_index_zero_node; @@ -7478,7 +7483,7 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr) if (!se->direct_byref) se->unlimited_polymorphic = UNLIMITED_POLY (expr); - + /* Special case things we know we can pass easily. */ switch (expr->expr_type) { @@ -8922,7 +8927,7 @@ static gfc_actual_arglist *pdt_param_list; static tree structure_alloc_comps (gfc_symbol * der_type, tree decl, tree dest, int rank, int purpose, int caf_mode, - gfc_co_subroutines_args *args) + gfc_co_subroutines_args *args, bool no_finalization) { gfc_component *c; gfc_loopinfo loop; @@ -9010,11 +9015,12 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, gfc_conv_array_data (dest)); dref = gfc_build_array_ref (tmp, index, NULL); tmp = structure_alloc_comps (der_type, vref, dref, rank, - COPY_ALLOC_COMP, caf_mode, args); + COPY_ALLOC_COMP, caf_mode, args, + no_finalization); } else tmp = structure_alloc_comps (der_type, vref, NULL_TREE, rank, purpose, - caf_mode, args); + caf_mode, args, no_finalization); gfc_add_expr_to_block (&loopbody, tmp); @@ -9048,13 +9054,15 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, if (purpose == DEALLOCATE_ALLOC_COMP && der_type->attr.pdt_type) { tmp = structure_alloc_comps (der_type, decl, NULL_TREE, rank, - DEALLOCATE_PDT_COMP, 0, args); + DEALLOCATE_PDT_COMP, 0, args, + no_finalization); gfc_add_expr_to_block (&fnblock, tmp); } else if (purpose == ALLOCATE_PDT_COMP && der_type->attr.alloc_comp) { tmp = structure_alloc_comps (der_type, decl, NULL_TREE, rank, - NULLIFY_ALLOC_COMP, 0, args); + NULLIFY_ALLOC_COMP, 0, args, + no_finalization); gfc_add_expr_to_block (&fnblock, tmp); } @@ -9112,7 +9120,7 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, add_when_allocated = structure_alloc_comps (CLASS_DATA (c)->ts.u.derived, comp, NULL_TREE, rank, purpose, - caf_mode, args); + caf_mode, args, no_finalization); } else { @@ -9120,7 +9128,8 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, add_when_allocated = structure_alloc_comps (c->ts.u.derived, comp, NULL_TREE, rank, purpose, - caf_mode, args); + caf_mode, args, + no_finalization); } } @@ -9216,8 +9225,8 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, continue; } - if ((c->ts.type == BT_DERIVED && !c->attr.pointer) - || (c->ts.type == BT_CLASS && !CLASS_DATA (c)->attr.class_pointer)) + if (!no_finalization && ((c->ts.type == BT_DERIVED && !c->attr.pointer) + || (c->ts.type == BT_CLASS && !CLASS_DATA (c)->attr.class_pointer))) /* Call the finalizer, which will free the memory and nullify the pointer of an array. */ deallocate_called = gfc_add_comp_finalizer_call (&tmpblock, comp, c, @@ -9245,7 +9254,7 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, add_when_allocated = structure_alloc_comps (CLASS_DATA (c)->ts.u.derived, comp, NULL_TREE, rank, purpose, - caf_mode, args); + caf_mode, args, no_finalization); } else { @@ -9253,7 +9262,8 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, add_when_allocated = structure_alloc_comps (c->ts.u.derived, comp, NULL_TREE, rank, purpose, - caf_mode, args); + caf_mode, args, + no_finalization); } } @@ -9551,7 +9561,8 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, decl, cdecl, NULL_TREE); rank = c->as ? c->as->rank : 0; tmp = structure_alloc_comps (c->ts.u.derived, comp, NULL_TREE, - rank, purpose, caf_mode, args); + rank, purpose, caf_mode, args, + no_finalization); gfc_add_expr_to_block (&fnblock, tmp); } break; @@ -9587,7 +9598,7 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, tmp = structure_alloc_comps (c->ts.u.derived, comp, dcmp, rank, purpose, caf_mode | GFC_STRUCTURE_CAF_MODE_IN_COARRAY, - args); + args, no_finalization); gfc_add_expr_to_block (&fnblock, tmp); } } @@ -9695,7 +9706,8 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, add_when_allocated = structure_alloc_comps (c->ts.u.derived, comp, dcmp, rank, purpose, - caf_mode, args); + caf_mode, args, + no_finalization); } else add_when_allocated = NULL_TREE; @@ -10068,7 +10080,8 @@ gfc_nullify_alloc_comp (gfc_symbol * der_type, tree decl, int rank, { return structure_alloc_comps (der_type, decl, NULL_TREE, rank, NULLIFY_ALLOC_COMP, - GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY | caf_mode, NULL); + GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY | caf_mode, + NULL, false); } @@ -10081,7 +10094,8 @@ gfc_deallocate_alloc_comp (gfc_symbol * der_type, tree decl, int rank, { return structure_alloc_comps (der_type, decl, NULL_TREE, rank, DEALLOCATE_ALLOC_COMP, - GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY | caf_mode, NULL); + GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY | caf_mode, + NULL, false); } tree @@ -10119,7 +10133,8 @@ gfc_bcast_alloc_comp (gfc_symbol *derived, gfc_expr *expr, int rank, tmp = structure_alloc_comps (derived, array, NULL_TREE, rank, BCAST_ALLOC_COMP, - GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY, &args); + GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY, + &args, false); return tmp; } @@ -10129,10 +10144,12 @@ gfc_bcast_alloc_comp (gfc_symbol *derived, gfc_expr *expr, int rank, status of coarrays. */ tree -gfc_deallocate_alloc_comp_no_caf (gfc_symbol * der_type, tree decl, int rank) +gfc_deallocate_alloc_comp_no_caf (gfc_symbol * der_type, tree decl, int rank, + bool no_finalization) { return structure_alloc_comps (der_type, decl, NULL_TREE, rank, - DEALLOCATE_ALLOC_COMP, 0, NULL); + DEALLOCATE_ALLOC_COMP, 0, NULL, + no_finalization); } @@ -10140,7 +10157,8 @@ tree gfc_reassign_alloc_comp_caf (gfc_symbol *der_type, tree decl, tree dest) { return structure_alloc_comps (der_type, decl, dest, 0, REASSIGN_CAF_COMP, - GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY, NULL); + GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY, + NULL, false); } @@ -10152,7 +10170,7 @@ gfc_copy_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank, int caf_mode) { return structure_alloc_comps (der_type, decl, dest, rank, COPY_ALLOC_COMP, - caf_mode, NULL); + caf_mode, NULL, false); } @@ -10163,7 +10181,7 @@ tree gfc_copy_only_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank) { return structure_alloc_comps (der_type, decl, dest, rank, - COPY_ONLY_ALLOC_COMP, 0, NULL); + COPY_ONLY_ALLOC_COMP, 0, NULL, false); } @@ -10178,7 +10196,7 @@ gfc_allocate_pdt_comp (gfc_symbol * der_type, tree decl, int rank, gfc_actual_arglist *old_param_list = pdt_param_list; pdt_param_list = param_list; res = structure_alloc_comps (der_type, decl, NULL_TREE, rank, - ALLOCATE_PDT_COMP, 0, NULL); + ALLOCATE_PDT_COMP, 0, NULL, false); pdt_param_list = old_param_list; return res; } @@ -10190,7 +10208,7 @@ tree gfc_deallocate_pdt_comp (gfc_symbol * der_type, tree decl, int rank) { return structure_alloc_comps (der_type, decl, NULL_TREE, rank, - DEALLOCATE_PDT_COMP, 0, NULL); + DEALLOCATE_PDT_COMP, 0, NULL, false); } @@ -10205,7 +10223,7 @@ gfc_check_pdt_dummy (gfc_symbol * der_type, tree decl, int rank, gfc_actual_arglist *old_param_list = pdt_param_list; pdt_param_list = param_list; res = structure_alloc_comps (der_type, decl, NULL_TREE, rank, - CHECK_PDT_DUMMY, 0, NULL); + CHECK_PDT_DUMMY, 0, NULL, false); pdt_param_list = old_param_list; return res; } @@ -10926,7 +10944,7 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop, && expr1->ts.u.derived->attr.alloc_comp) { tmp = gfc_deallocate_alloc_comp_no_caf (expr1->ts.u.derived, old_desc, - expr1->rank); + expr1->rank, true); gfc_add_expr_to_block (&realloc_block, tmp); } diff --git a/gcc/fortran/trans-array.h b/gcc/fortran/trans-array.h index 04fee617590..3aae4d2c4eb 100644 --- a/gcc/fortran/trans-array.h +++ b/gcc/fortran/trans-array.h @@ -56,7 +56,8 @@ tree gfc_nullify_alloc_comp (gfc_symbol *, tree, int, int cm = 0); tree gfc_deallocate_alloc_comp (gfc_symbol *, tree, int, int cm = 0); tree gfc_bcast_alloc_comp (gfc_symbol *, gfc_expr *, int, tree, tree, tree, tree); -tree gfc_deallocate_alloc_comp_no_caf (gfc_symbol *, tree, int); +tree gfc_deallocate_alloc_comp_no_caf (gfc_symbol *, tree, int, + bool no_finalization = false); tree gfc_reassign_alloc_comp_caf (gfc_symbol *, tree, tree); tree gfc_copy_alloc_comp (gfc_symbol *, tree, tree, int, int); diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc index eb6a78c3a62..6ffe317afbf 100644 --- a/gcc/fortran/trans-expr.cc +++ b/gcc/fortran/trans-expr.cc @@ -1904,6 +1904,7 @@ gfc_init_se (gfc_se * se, gfc_se * parent) { memset (se, 0, sizeof (gfc_se)); gfc_init_block (&se->pre); + gfc_init_block (&se->finalblock); gfc_init_block (&se->post); se->parent = parent; @@ -5975,6 +5976,116 @@ post_call: } +/* Finalize a function result using the finalizer wrapper. The result is fixed + in order to prevent repeated calls. */ + +static void +finalize_function_result (gfc_se *se, gfc_symbol *derived, + symbol_attribute attr) +{ + tree vptr, final_fndecl, desc, tmp, size, is_final, data_ptr; + gfc_symbol *vtab; + gfc_se post_se; + bool is_class = GFC_CLASS_TYPE_P (TREE_TYPE (se->expr)); + + if (attr.pointer) + return; + + if (is_class) + { + if (!VAR_P (se->expr)) + { + desc = gfc_evaluate_now (se->expr, &se->pre); + se->expr = desc; + } + desc = gfc_class_data_get (se->expr); + vptr = gfc_class_vptr_get (se->expr); + } + else + { + desc = gfc_evaluate_now (se->expr, &se->pre); + se->expr = gfc_evaluate_now (desc, &se->pre); + gfc_add_expr_to_block (&se->pre, + gfc_copy_alloc_comp (derived, se->expr, + desc, 0, 0)); + vtab = gfc_find_derived_vtab (derived); + if (vtab->backend_decl == NULL_TREE) + vptr = gfc_get_symbol_decl (vtab); + else + vptr = vtab->backend_decl; + vptr = gfc_build_addr_expr (NULL, vptr); + } + + size = gfc_vptr_size_get (vptr); + final_fndecl = gfc_vptr_final_get (vptr); + is_final = fold_build2_loc (input_location, NE_EXPR, + logical_type_node, + final_fndecl, + fold_convert (TREE_TYPE (final_fndecl), + null_pointer_node)); + + final_fndecl = build_fold_indirect_ref_loc (input_location, + final_fndecl); + if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))) + { + if (is_class) + desc = gfc_conv_scalar_to_descriptor (se, desc, attr); + else + { + gfc_init_se (&post_se, NULL); + desc = gfc_conv_scalar_to_descriptor (&post_se, desc, attr); + gfc_add_expr_to_block (&se->pre, gfc_finish_block (&post_se.pre)); + } + } + + tmp = gfc_create_var (TREE_TYPE (desc), "res"); + gfc_add_modify (&se->pre, tmp, desc); + desc = tmp; + + tmp = build_call_expr_loc (input_location, final_fndecl, 3, + gfc_build_addr_expr (NULL, desc), + size, boolean_false_node); + + tmp = fold_build3_loc (input_location, COND_EXPR, + void_type_node, is_final, tmp, + build_empty_stmt (input_location)); + + if (is_class && se->ss && se->ss->loop) + { + data_ptr = gfc_conv_descriptor_data_get (desc); + + gfc_add_expr_to_block (&se->loop->post, tmp); + tmp = fold_build2_loc (input_location, NE_EXPR, + logical_type_node, + data_ptr, + fold_convert (TREE_TYPE (data_ptr), + null_pointer_node)); + tmp = fold_build3_loc (input_location, COND_EXPR, + void_type_node, tmp, + gfc_call_free (data_ptr), + build_empty_stmt (input_location)); + gfc_add_expr_to_block (&se->loop->post, tmp); + } + else + { + gfc_add_expr_to_block (&se->finalblock, tmp); + if (is_class) + { + data_ptr = gfc_conv_descriptor_data_get (desc); + tmp = fold_build2_loc (input_location, NE_EXPR, + logical_type_node, + data_ptr, + fold_convert (TREE_TYPE (data_ptr), + null_pointer_node)); + tmp = fold_build3_loc (input_location, COND_EXPR, + void_type_node, tmp, + gfc_call_free (data_ptr), + build_empty_stmt (input_location)); + gfc_add_expr_to_block (&se->finalblock, tmp); + } + } +} + /* Generate code for a procedure call. Note can return se->post != NULL. If se->direct_byref is set then se->expr contains the return parameter. Return nonzero, if the call has alternate specifiers. @@ -7011,6 +7122,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, gfc_add_block_to_block (&se->pre, &parmse.pre); gfc_add_block_to_block (&post, &parmse.post); + gfc_add_block_to_block (&se->finalblock, &parmse.finalblock); /* Allocated allocatable components of derived types must be deallocated for non-variable scalars, array arguments to elemental @@ -7675,9 +7787,17 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, /* Allocatable scalar function results must be freed and nullified after use. This necessitates the creation of a temporary to hold the result to prevent duplicate calls. */ + symbol_attribute attr = comp ? comp->attr : sym->attr; + bool allocatable = attr.allocatable && !attr.dimension; + gfc_symbol *der = comp && comp->ts.type == BT_DERIVED ? comp->ts.u.derived + : (sym->ts.type == BT_DERIVED ? sym->ts.u.derived : NULL); + bool finalizable = der != NULL && gfc_is_finalizable (der, NULL); + + if (!byref && finalizable) + finalize_function_result (se, der, attr); + if (!byref && sym->ts.type != BT_CHARACTER - && ((sym->attr.allocatable && !sym->attr.dimension && !comp) - || (comp && comp->attr.allocatable && !comp->attr.dimension))) + && allocatable && !finalizable) { tmp = gfc_create_var (TREE_TYPE (se->expr), NULL); gfc_add_modify (&se->pre, tmp, se->expr); @@ -7737,6 +7857,9 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, se->expr = info->descriptor; /* Bundle in the string length. */ se->string_length = len; + + if (finalizable) + finalize_function_result (se, der, attr); } else if (ts.type == BT_CHARACTER) { @@ -7829,8 +7952,6 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, && se->expr && GFC_CLASS_TYPE_P (TREE_TYPE (se->expr)) && expr->must_finalize) { - tree final_fndecl; - tree is_final; int n; if (se->ss && se->ss->loop) { @@ -7852,66 +7973,15 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, /* TODO Eliminate the doubling of temporaries. This one is necessary to ensure no memory leakage. */ se->expr = gfc_evaluate_now (se->expr, &se->pre); - tmp = gfc_class_data_get (se->expr); - tmp = gfc_conv_scalar_to_descriptor (se, tmp, - CLASS_DATA (expr->value.function.esym->result)->attr); } - if ((gfc_is_class_array_function (expr) - || gfc_is_alloc_class_scalar_function (expr)) - && CLASS_DATA (expr->value.function.esym->result)->attr.pointer) - goto no_finalization; - - final_fndecl = gfc_class_vtab_final_get (se->expr); - is_final = fold_build2_loc (input_location, NE_EXPR, - logical_type_node, - final_fndecl, - fold_convert (TREE_TYPE (final_fndecl), - null_pointer_node)); - final_fndecl = build_fold_indirect_ref_loc (input_location, - final_fndecl); - tmp = build_call_expr_loc (input_location, - final_fndecl, 3, - gfc_build_addr_expr (NULL, tmp), - gfc_class_vtab_size_get (se->expr), - boolean_false_node); - tmp = fold_build3_loc (input_location, COND_EXPR, - void_type_node, is_final, tmp, - build_empty_stmt (input_location)); - - if (se->ss && se->ss->loop) - { - gfc_prepend_expr_to_block (&se->ss->loop->post, tmp); - tmp = fold_build2_loc (input_location, NE_EXPR, - logical_type_node, - info->data, - fold_convert (TREE_TYPE (info->data), - null_pointer_node)); - tmp = fold_build3_loc (input_location, COND_EXPR, - void_type_node, tmp, - gfc_call_free (info->data), - build_empty_stmt (input_location)); - gfc_add_expr_to_block (&se->ss->loop->post, tmp); - } - else - { - tree classdata; - gfc_prepend_expr_to_block (&se->post, tmp); - classdata = gfc_class_data_get (se->expr); - tmp = fold_build2_loc (input_location, NE_EXPR, - logical_type_node, - classdata, - fold_convert (TREE_TYPE (classdata), - null_pointer_node)); - tmp = fold_build3_loc (input_location, COND_EXPR, - void_type_node, tmp, - gfc_call_free (classdata), - build_empty_stmt (input_location)); - gfc_add_expr_to_block (&se->post, tmp); - } + /* Finalize the result, if necessary. */ + attr = CLASS_DATA (expr->value.function.esym->result)->attr; + if (!((gfc_is_class_array_function (expr) + || gfc_is_alloc_class_scalar_function (expr)) + && attr.pointer)) + finalize_function_result (se, NULL, attr); } - -no_finalization: gfc_add_block_to_block (&se->post, &post); } @@ -10430,7 +10500,8 @@ gfc_trans_scalar_assign (gfc_se * lse, gfc_se * rse, gfc_typespec ts, if (dealloc) { tmp_var = gfc_evaluate_now (lse->expr, &lse->pre); - tmp = gfc_deallocate_alloc_comp_no_caf (ts.u.derived, tmp_var, 0); + tmp = gfc_deallocate_alloc_comp_no_caf (ts.u.derived, tmp_var, + 0, true); if (deep_copy) tmp = build3_v (COND_EXPR, cond, build_empty_stmt (input_location), tmp); @@ -10872,6 +10943,7 @@ gfc_trans_arrayfunc_assign (gfc_expr * expr1, gfc_expr * expr2) gfc_conv_function_expr (&se, expr2); gfc_add_block_to_block (&se.pre, &se.post); + gfc_add_block_to_block (&se.pre, &se.finalblock); if (ss) gfc_cleanup_loop (&loop); @@ -11387,6 +11459,89 @@ is_runtime_conformable (gfc_expr *expr1, gfc_expr *expr2) } + /* F2018 (7.5.6.3): "When an intrinsic assignment statement is executed + (10.2.1.3), if the variable is not an unallocated allocatable variable, + it is finalized after evaluation of expr and before the definition of + the variable. If the variable is an allocated allocatable variable, or + has an allocated allocatable subobject, that would be deallocated by + intrinsic assignment, the finalization occurs before the deallocation */ + +static tree +gfc_assignment_finalizer_call (gfc_expr *expr1, bool init_flag) +{ + stmtblock_t final_block; + gfc_init_block (&final_block); + symbol_attribute lhs_attr; + tree final_expr; + tree ptr; + tree cond; + gfc_se se; + + /* We have to exclude vtable procedures (_copy and _final especially), uses + of gfc_trans_assignment_1 in initialization and allocation before trying + to build a final call. */ + if (!expr1->must_finalize + || expr1->symtree->n.sym->attr.artificial + || expr1->symtree->n.sym->ns->proc_name->attr.artificial + || init_flag) + return NULL_TREE; + + if (!(expr1->ts.type == BT_CLASS + || (expr1->ts.type == BT_DERIVED + && gfc_is_finalizable (expr1->ts.u.derived, NULL))) + || !gfc_add_finalizer_call (&final_block, expr1)) + return NULL_TREE; + + lhs_attr = gfc_expr_attr (expr1); + + /* Check allocatable/pointer is allocated/associated. */ + if (lhs_attr.allocatable || lhs_attr.pointer) + { + if (expr1->ts.type == BT_CLASS) + { + ptr = gfc_get_class_from_gfc_expr (expr1); + gcc_assert (ptr != NULL_TREE); + ptr = gfc_class_data_get (ptr); + if (lhs_attr.dimension) + ptr = gfc_conv_descriptor_data_get (ptr); + } + else + { + gfc_init_se (&se, NULL); + if (expr1->rank) + { + gfc_conv_expr_descriptor (&se, expr1); + ptr = gfc_conv_descriptor_data_get (se.expr); + } + else + { + gfc_conv_expr (&se, expr1); + ptr = gfc_build_addr_expr (NULL_TREE, se.expr); + } + } + + cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, + ptr, build_zero_cst (TREE_TYPE (ptr))); + final_expr = build3_loc (input_location, COND_EXPR, void_type_node, + cond, gfc_finish_block (&final_block), + build_empty_stmt (input_location)); + } + else + final_expr = gfc_finish_block (&final_block); + + /* Check optional present. */ + if (expr1->symtree->n.sym->attr.optional) + { + cond = gfc_conv_expr_present (expr1->symtree->n.sym); + final_expr = build3_loc (input_location, COND_EXPR, void_type_node, + cond, final_expr, + build_empty_stmt (input_location)); + } + + return final_expr; +} + + static tree trans_class_assignment (stmtblock_t *block, gfc_expr *lhs, gfc_expr *rhs, gfc_se *lse, gfc_se *rse, bool use_vptr_copy, @@ -11394,6 +11549,16 @@ trans_class_assignment (stmtblock_t *block, gfc_expr *lhs, gfc_expr *rhs, { tree tmp, fcn, stdcopy, to_len, from_len, vptr, old_vptr; vec<tree, va_gc> *args = NULL; + tree final_expr; + + final_expr = gfc_assignment_finalizer_call (lhs, false); + if (final_expr != NULL_TREE) + { + if (rse->loop) + gfc_prepend_expr_to_block (&rse->loop->pre, final_expr); + else + gfc_add_expr_to_block (block, final_expr); + } /* Store the old vptr so that dynamic types can be compared for reallocation to occur or not. */ @@ -11419,8 +11584,12 @@ trans_class_assignment (stmtblock_t *block, gfc_expr *lhs, gfc_expr *rhs, old_vptr = build_int_cst (TREE_TYPE (vptr), 0); size = gfc_vptr_size_get (vptr); - class_han = GFC_CLASS_TYPE_P (TREE_TYPE (lse->expr)) - ? gfc_class_data_get (lse->expr) : lse->expr; + if (TREE_CODE (lse->expr) == INDIRECT_REF) + tmp = TREE_OPERAND (lse->expr, 0); + else + tmp = lse->expr; + class_han = GFC_CLASS_TYPE_P (TREE_TYPE (tmp)) + ? gfc_class_data_get (tmp) : tmp; /* Allocate block. */ gfc_init_block (&alloc); @@ -11519,6 +11688,7 @@ trans_class_assignment (stmtblock_t *block, gfc_expr *lhs, gfc_expr *rhs, } } + /* Subroutine of gfc_trans_assignment that actually scalarizes the assignment. EXPR1 is the destination/LHS and EXPR2 is the source/RHS. init_flag indicates initialization expressions and dealloc that no @@ -11542,6 +11712,7 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag, tree tmp; stmtblock_t block; stmtblock_t body; + tree final_expr; bool l_is_temp; bool scalar_to_array; tree string_length; @@ -11582,6 +11753,7 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag, needed at two locations, so do it once only before the information is needed. */ lhs_attr = gfc_expr_attr (expr1); + is_poly_assign = (use_vptr_copy || lhs_attr.pointer || (lhs_attr.allocatable && !lhs_attr.dimension)) && (expr1->ts.type == BT_CLASS @@ -11855,6 +12027,8 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag, else gfc_add_expr_to_block (&loop.post, tmp2); } + + expr1->must_finalize = 0; } else if (flag_coarray == GFC_FCOARRAY_LIB && lhs_caf_attr.codimension && rhs_caf_attr.codimension @@ -11909,12 +12083,36 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag, !(l_is_temp || init_flag) && dealloc, expr1->symtree->n.sym->attr.codimension); - /* Add the pre blocks to the body. */ - gfc_add_block_to_block (&body, &rse.pre); + /* Comply with F2018 (7.5.6.3). Make sure that any finalization code is added + after evaluation of the rhs and before reallocation. */ + final_expr = gfc_assignment_finalizer_call (expr1, init_flag); + if (final_expr) + { + if (lss == gfc_ss_terminator) + { + gfc_add_block_to_block (&block, &rse.pre); + gfc_add_expr_to_block (&block, final_expr); + } + else + { + gfc_add_block_to_block (&body, &rse.pre); + gfc_add_expr_to_block (&loop.code[expr1->rank - 1], final_expr); + } + } + else + gfc_add_block_to_block (&body, &rse.pre); + + /* Add the lse pre block to the body */ gfc_add_block_to_block (&body, &lse.pre); gfc_add_expr_to_block (&body, tmp); /* Add the post blocks to the body. */ - gfc_add_block_to_block (&body, &rse.post); + if (lss == gfc_ss_terminator) + { + gfc_add_block_to_block (&rse.finalblock, &rse.post); + gfc_add_block_to_block (&body, &rse.finalblock); + } + else + gfc_add_block_to_block (&body, &rse.post); gfc_add_block_to_block (&body, &lse.post); if (lss == gfc_ss_terminator) @@ -11979,6 +12177,7 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag, /* Wrap the whole thing up. */ gfc_add_block_to_block (&block, &loop.pre); gfc_add_block_to_block (&block, &loop.post); + gfc_add_block_to_block (&block, &rse.finalblock); gfc_cleanup_loop (&loop); } diff --git a/gcc/fortran/trans-io.cc b/gcc/fortran/trans-io.cc index 732221f848b..bf4f0671585 100644 --- a/gcc/fortran/trans-io.cc +++ b/gcc/fortran/trans-io.cc @@ -2664,6 +2664,7 @@ scalarize: gfc_add_block_to_block (&body, &se.pre); gfc_add_block_to_block (&body, &se.post); + gfc_add_block_to_block (&body, &se.finalblock); if (se.ss == NULL) tmp = gfc_finish_block (&body); diff --git a/gcc/fortran/trans-stmt.cc b/gcc/fortran/trans-stmt.cc index 04f8147d23b..e0f513f8941 100644 --- a/gcc/fortran/trans-stmt.cc +++ b/gcc/fortran/trans-stmt.cc @@ -443,7 +443,8 @@ gfc_trans_call (gfc_code * code, bool dependency_check, else gfc_add_expr_to_block (&se.pre, se.expr); - gfc_add_block_to_block (&se.pre, &se.post); + gfc_add_block_to_block (&se.finalblock, &se.post); + gfc_add_block_to_block (&se.pre, &se.finalblock); } else @@ -542,6 +543,7 @@ gfc_trans_call (gfc_code * code, bool dependency_check, gfc_trans_scalarizing_loops (&loop, &body); gfc_add_block_to_block (&se.pre, &loop.pre); gfc_add_block_to_block (&se.pre, &loop.post); + gfc_add_block_to_block (&se.pre, &loopse.finalblock); gfc_add_block_to_block (&se.pre, &se.post); gfc_cleanup_loop (&loop); } @@ -6337,7 +6339,10 @@ gfc_trans_allocate (gfc_code * code) } gfc_add_block_to_block (&block, &se.pre); if (code->expr3->must_finalize) - gfc_add_block_to_block (&final_block, &se.post); + { + gfc_add_block_to_block (&final_block, &se.finalblock); + gfc_add_block_to_block (&final_block, &se.post); + } else gfc_add_block_to_block (&post, &se.post); diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h index 738c7487a56..72af54c4d29 100644 --- a/gcc/fortran/trans.h +++ b/gcc/fortran/trans.h @@ -43,6 +43,10 @@ typedef struct gfc_se stmtblock_t pre; stmtblock_t post; + /* Carries finalization code that is required to be executed execution of the + innermost executable construct. */ + stmtblock_t finalblock; + /* the result of the expression */ tree expr; @@ -55,7 +59,7 @@ typedef struct gfc_se /* Whether expr is a reference to an unlimited polymorphic object. */ unsigned unlimited_polymorphic:1; - + /* If set gfc_conv_variable will return an expression for the array descriptor. When set, want_pointer should also be set. If not set scalarizing variables will be substituted. */ diff --git a/gcc/testsuite/gfortran.dg/allocate_with_source_25.f90 b/gcc/testsuite/gfortran.dg/allocate_with_source_25.f90 index 92dc50756d4..de20a147842 100644 --- a/gcc/testsuite/gfortran.dg/allocate_with_source_25.f90 +++ b/gcc/testsuite/gfortran.dg/allocate_with_source_25.f90 @@ -68,4 +68,4 @@ contains end function func_foo_a end program simple_leak -! { dg-final { scan-tree-dump-times "\>_final" 6 "original" } } +! { dg-final { scan-tree-dump-times "\>_final" 4 "original" } } ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: FINAL subroutines 2022-01-27 22:10 ` Paul Richard Thomas @ 2022-01-28 8:05 ` Salvatore Filippone 2022-01-28 9:01 ` Paul Richard Thomas 0 siblings, 1 reply; 10+ messages in thread From: Salvatore Filippone @ 2022-01-28 8:05 UTC (permalink / raw) To: Paul Richard Thomas; +Cc: Jerry D, Andrew Benson, Damian Rouson, Fortran List So, you are saying that three calls is the correct number, one for the LHS, one for the RHS, and one for the deallocation in the main program. I have (re)-read the standard, I would concur with your interpretation. On Thu, Jan 27, 2022 at 11:10 PM Paul Richard Thomas < paul.richard.thomas@gmail.com> wrote: > Hi Salvatore, > > > My reading of F2018: 7.5.6.3 "When finalization occurs" is that three > calls is correct. (i) Paragraph 1 stipulates that the 'var' expression be > evaluated before the reallocation and intrinsic assignment; (ii)stipulates > that the function result be finalised "the result is finalized after > execution of the innermost > executable construct containing the reference." ; and (iii) Finalisation > occurs on going out of scope. > > That is what is implemented in the attached. I am working my way through > the testcase dependencies of PR37336 making sure that finalizat > ion occurs as required by 7.5.6.3 and in the order defined in the previous > section. It will all be done in the next few days. > > What will remain is finalization of function results within array > constructors and one or two other corner cases. Following that, the > existing finalization calls will be brought into the framework as the new > calls. > > Best regards > > Paul > > > On Thu, 27 Jan 2022 at 07:17, Salvatore Filippone < > filippone.salvatore@gmail.com> wrote: > >> One more data point: Cray FTN issues TWO calls to the FINAL. >> Which begs the question: what is the correct number of calls one, two or >> three? >> Salvatore >> >> fsalvato@daint102:/project/prce01/fsalvato/NUMERICAL/PSBLAS/V4/psblas4/test/newstuff> >> ftn --version >> Cray Fortran : Version 11.0.0 >> fsalvato@daint102:/project/prce01/fsalvato/NUMERICAL/PSBLAS/V4/psblas4/test/newstuff> >> ftn -o testfinal testfinal.f90 >> fsalvato@daint102:/project/prce01/fsalvato/NUMERICAL/PSBLAS/V4/psblas4/test/newstuff> >> ./testfinal >> Allocating wrapper >> Calling new_outer_type >> Assigning outer%test_item >> Called delete_test_type >> End of new_outer_type >> DeAllocating wrapper >> Called delete_test_type >> >> On Wed, Jan 26, 2022 at 11:59 PM Paul Richard Thomas < >> paul.richard.thomas@gmail.com> wrote: >> >>> Hi Jerry, >>> >>> I am trying to fix the failure of my latest patch with this very test >>> case. Otherwise it fixes most of the remaining dependencies in PR37336. >>> >>> At a pinch, I could submit the earlier patch that Andrew mentions and >>> work from there. However, you will note that it does miss one of the >>> finalizations. This is critical because function results, which should be >>> finalized, are not. >>> >>> I'll keep an eye on the state of the branch. By and large, release >>> occurs 3-4 months after the start of stage 4. I will leave 2 months maximum. >>> >>> Best regards >>> >>> Paul >>> >>> >>> On Wed, 26 Jan 2022 at 21:29, Jerry D via Fortran <fortran@gcc.gnu.org> >>> wrote: >>> >>>> Is there any reason these patches can not be applied and use this test >>>> as a test case? >>>> >>>> Regards, >>>> >>>> Jerry >>>> >>>> On 1/24/22 8:11 AM, Salvatore Filippone via Fortran wrote: >>>> > Thanks a lot >>>> > (yes, I suspected both gfortran and intel were wrong, precisely >>>> because I >>>> > could see why you'd need two FINAL calls, but not three). >>>> > >>>> > Salvatore >>>> > >>>> > On Mon, Jan 24, 2022 at 4:45 PM Andrew Benson < >>>> abenson@carnegiescience.edu> >>>> > wrote: >>>> > >>>> >> Hi Salvatore, >>>> >> >>>> >> This looks like it's related to some of the missing finalization >>>> >> functionality >>>> >> (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37336). Paul has some >>>> >> patches >>>> >> (e.g. https://gcc.gnu.org/pipermail/fortran/2022-January/057415.html >>>> ) >>>> >> which >>>> >> implement most of the missing functionality. With those patches >>>> >> incorporated >>>> >> your code gives the following output with gfortran: >>>> >> >>>> >> $ ./testfinal >>>> >> Allocating wrapper >>>> >> Calling new_outer_type >>>> >> Assigning outer%test_item >>>> >> Called delete_test_type >>>> >> End of new_outer_type >>>> >> DeAllocating wrapper >>>> >> Called delete_test_type >>>> >> >>>> >> So there is one more call to the finalizer than you found - I haven't >>>> >> checked >>>> >> carefully but I would guess this is a deallocation of LHS on >>>> assignment. >>>> >> >>>> >> In testing these patches using the Intel compiler we found that it >>>> seems >>>> >> to >>>> >> call the finalization wrapper more than it should, sometimes on >>>> objects >>>> >> that >>>> >> have already been deallocated. Your code, compiled with the Intel >>>> compiler >>>> >> and >>>> >> then run under valgrind shows the following: >>>> >> >>>> >> $ valgrind ./testfinal >>>> >> ==7340== Memcheck, a memory error detector >>>> >> ==7340== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et >>>> al. >>>> >> ==7340== Using Valgrind-3.13.0 and LibVEX; rerun with -h for >>>> copyright info >>>> >> ==7340== Command: ./testfinal >>>> >> ==7340== >>>> >> ==7340== Conditional jump or move depends on uninitialised value(s) >>>> >> ==7340== at 0x493A51: __intel_sse2_strcpy (in >>>> /home/abensonca/Scratch/ >>>> >> ifortTests/testfinal) >>>> >> ==7340== by 0x45D70E: for__add_to_lf_table (in >>>> /home/abensonca/Scratch/ >>>> >> ifortTests/testfinal) >>>> >> ==7340== by 0x4410CB: for__open_proc (in /home/abensonca/Scratch/ >>>> >> ifortTests/testfinal) >>>> >> ==7340== by 0x423A64: for__open_default (in >>>> /home/abensonca/Scratch/ >>>> >> ifortTests/testfinal) >>>> >> ==7340== by 0x4305A9: for_write_seq_lis (in >>>> /home/abensonca/Scratch/ >>>> >> ifortTests/testfinal) >>>> >> ==7340== by 0x4047E1: MAIN__ (testfinal.f90:62) >>>> >> ==7340== by 0x403CE1: main (in /home/abensonca/Scratch/ifortTests/ >>>> >> testfinal) >>>> >> ==7340== >>>> >> Allocating wrapper >>>> >> Calling new_outer_type >>>> >> Assigning outer%test_item >>>> >> Called delete_test_type >>>> >> ==7340== Conditional jump or move depends on uninitialised value(s) >>>> >> ==7340== at 0x40572A: do_alloc_copy (in >>>> >> /home/abensonca/Scratch/ifortTests/ >>>> >> testfinal) >>>> >> ==7340== by 0x406B9A: do_alloc_copy (in >>>> >> /home/abensonca/Scratch/ifortTests/ >>>> >> testfinal) >>>> >> ==7340== by 0x4084ED: for_alloc_assign_v2 (in >>>> /home/abensonca/Scratch/ >>>> >> ifortTests/testfinal) >>>> >> ==7340== by 0x404474: target_mod_mp_new_outer_type_ >>>> (testfinal.f90:48) >>>> >> ==7340== by 0x40485E: MAIN__ (testfinal.f90:65) >>>> >> ==7340== by 0x403CE1: main (in /home/abensonca/Scratch/ifortTests/ >>>> >> testfinal) >>>> >> ==7340== >>>> >> Called delete_test_type >>>> >> End of new_outer_type >>>> >> DeAllocating wrapper >>>> >> Called delete_test_type >>>> >> ==7340== >>>> >> ==7340== HEAP SUMMARY: >>>> >> ==7340== in use at exit: 48 bytes in 1 blocks >>>> >> ==7340== total heap usage: 14 allocs, 13 frees, 12,879 bytes >>>> allocated >>>> >> ==7340== >>>> >> ==7340== LEAK SUMMARY: >>>> >> ==7340== definitely lost: 48 bytes in 1 blocks >>>> >> ==7340== indirectly lost: 0 bytes in 0 blocks >>>> >> ==7340== possibly lost: 0 bytes in 0 blocks >>>> >> ==7340== still reachable: 0 bytes in 0 blocks >>>> >> ==7340== suppressed: 0 bytes in 0 blocks >>>> >> ==7340== Rerun with --leak-check=full to see details of leaked memory >>>> >> ==7340== >>>> >> ==7340== For counts of detected and suppressed errors, rerun with: -v >>>> >> ==7340== Use --track-origins=yes to see where uninitialised values >>>> come >>>> >> from >>>> >> ==7340== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from >>>> 0) >>>> >> >>>> >> so there are some cases of what look like incorrect accesses (and >>>> some >>>> >> leaked >>>> >> memory). >>>> >> >>>> >> Your code compiled with gfortran (with Paul's patches in place) >>>> shows no >>>> >> errors or leaks from valgrind. >>>> >> >>>> >> So, in summary, in this case I think the current gfortran is missing >>>> some >>>> >> finalizations (which are fixed by Paul's patches), and ifort is >>>> likely >>>> >> doing >>>> >> something wrong and probably calling the finalizer more times than it >>>> >> should. >>>> >> >>>> >> -Andrew >>>> >> >>>> >> On Monday, January 24, 2022 6:49:23 AM PST Salvatore Filippone via >>>> Fortran >>>> >> wrote: >>>> >>> And here is the code embedded as text............ sorry about >>>> sending an >>>> >>> attachment that was purged >>>> >>> ------------------------- testfinal.f90 --------------------- >>>> >>> module test_type_mod >>>> >>> >>>> >>> type :: my_test_type >>>> >>> integer, allocatable :: i >>>> >>> contains >>>> >>> final :: delete_test_type >>>> >>> end type my_test_type >>>> >>> >>>> >>> interface my_test_type >>>> >>> module procedure new_test_type_object >>>> >>> end interface my_test_type >>>> >>> >>>> >>> contains >>>> >>> >>>> >>> subroutine delete_test_type(this) >>>> >>> type(my_test_type) :: this >>>> >>> >>>> >>> write(*,*) 'Called delete_test_type' >>>> >>> if (allocated(this%i)) deallocate(this%i) >>>> >>> >>>> >>> end subroutine delete_test_type >>>> >>> >>>> >>> >>>> >>> function new_test_type_object(item) result(res) >>>> >>> type(my_test_type) :: res >>>> >>> integer, intent(in) :: item >>>> >>> !Allocation on assignment >>>> >>> res%i=item >>>> >>> end function new_test_type_object >>>> >>> >>>> >>> >>>> >>> end module test_type_mod >>>> >>> >>>> >>> module target_mod >>>> >>> use test_type_mod >>>> >>> type :: outer_type >>>> >>> type(my_test_type), allocatable :: test_item >>>> >>> end type outer_type >>>> >>> >>>> >>> contains >>>> >>> >>>> >>> subroutine new_outer_type(outer,item) >>>> >>> type(outer_type), intent(out) :: outer >>>> >>> integer :: item >>>> >>> >>>> >>> allocate(outer%test_item) >>>> >>> write(*,*) 'Assigning outer%test_item' >>>> >>> outer%test_item = my_test_type(itemi) >>>> >>> write(*,*) 'End of new_outer_type' >>>> >>> end subroutine new_outer_type >>>> >>> >>>> >>> end module target_mod >>>> >>> >>>> >>> program testfinal >>>> >>> use target_mod >>>> >>> >>>> >>> implicit none >>>> >>> >>>> >>> integer :: i=10 >>>> >>> type(outer_type), allocatable :: wrapper >>>> >>> >>>> >>> write(*,*) 'Allocating wrapper ' >>>> >>> allocate(wrapper) >>>> >>> write(*,*) 'Calling new_outer_type ' >>>> >>> call new_outer_type(wrapper,i) >>>> >>> write(*,*) 'DeAllocating wrapper ' >>>> >>> deallocate(wrapper) >>>> >>> >>>> >>> end program testfinal >>>> >>> >>>> >>> On Mon, Jan 24, 2022 at 2:50 PM Salvatore Filippone < >>>> >>> >>>> >>> filippone.salvatore@gmail.com> wrote: >>>> >>>> Hi all >>>> >>>> The attached code compiles and runs fine under both GNU and Intel, >>>> but >>>> >> it >>>> >>>> produces different results, in particular the FINAL subroutine is >>>> >> invoked >>>> >>>> just once with GNU, three times with Intel. >>>> >>>> >>>> >>>> It seems to me that they cannot both be right; I am not sure what >>>> the >>>> >>>> standard is mandating in this case. >>>> >>>> Any ideas? >>>> >>>> Salvatore >>>> >>>> --------------- Intel >>>> >>>> [pr1eio03@login1: newstuff]$ ifort -v >>>> >>>> ifort version 19.1.1.217 >>>> >>>> [pr1eio03@login1: newstuff]$ ifort -o testfinal testfinal.f90 >>>> >>>> [pr1eio03@login1: newstuff]$ ./testfinal >>>> >>>> >>>> >>>> Allocating wrapper >>>> >>>> Calling new_outer_type >>>> >>>> Assigning outer%test_item >>>> >>>> Called delete_test_type >>>> >>>> Called delete_test_type >>>> >>>> End of new_outer_type >>>> >>>> DeAllocating wrapper >>>> >>>> Called delete_test_type >>>> >>>> >>>> >>>> ----------------------------- GNU >>>> >>>> sfilippo@lagrange newstuff]$ gfortran -v >>>> >>>> Using built-in specs. >>>> >>>> COLLECT_GCC=gfortran >>>> >>>> >>>> COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/11/lto-wrapper >>>> >>>> OFFLOAD_TARGET_NAMES=nvptx-none >>>> >>>> OFFLOAD_TARGET_DEFAULT=1 >>>> >>>> Target: x86_64-redhat-linux >>>> >>>> Configured with: ../configure --enable-bootstrap >>>> >>>> --enable-languages=c,c++,fortran,objc,obj-c++,ada,go,d,lto >>>> >> --prefix=/usr >>>> >>>> --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl= >>>> >>>> http://bugzilla.redhat.com/bugzilla --enable-shared >>>> >>>> --enable-threads=posix --enable-checking=release --enable-multilib >>>> >>>> --with-system-zlib --enable-__cxa_atexit >>>> --disable-libunwind-exceptions >>>> >>>> --enable-gnu-unique-object --enable-linker-build-id >>>> >>>> --with-gcc-major-version-only --with-linker-hash-style=gnu >>>> >> --enable-plugin >>>> >>>> --enable-initfini-array >>>> >>>> >>>> >> >>>> --with-isl=/builddir/build/BUILD/gcc-11.2.1-20210728/obj-x86_64-redhat-lin >>>> >>>> ux/isl-install --enable-offload-targets=nvptx-none >>>> >> --without-cuda-driver >>>> >>>> --enable-gnu-indirect-function --enable-cet --with-tune=generic >>>> >>>> --with-arch_32=i686 --build=x86_64-redhat-linux >>>> >>>> Thread model: posix >>>> >>>> Supported LTO compression algorithms: zlib zstd >>>> >>>> gcc version 11.2.1 20210728 (Red Hat 11.2.1-1) (GCC) >>>> >>>> [sfilippo@lagrange newstuff]$ gfortran -o testfinal testfinal.f90 >>>> >>>> [sfilippo@lagrange newstuff]$ ./testfinal >>>> >>>> >>>> >>>> Allocating wrapper >>>> >>>> Calling new_outer_type >>>> >>>> Assigning outer%test_item >>>> >>>> End of new_outer_type >>>> >>>> DeAllocating wrapper >>>> >>>> Called delete_test_type >>>> >>>> >>>> >>>> --------------------- >>>> >> >>>> >> -- >>>> >> >>>> >> * Andrew Benson: https://abensonca.github.io >>>> >> >>>> >> * Galacticus: https://github.com/galacticusorg/galacticus >>>> >> >>>> >> >>>> >> >>>> >> >>>> >>>> >>> >>> -- >>> "If you can't explain it simply, you don't understand it well enough" - >>> Albert Einstein >>> >> > > -- > "If you can't explain it simply, you don't understand it well enough" - > Albert Einstein > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: FINAL subroutines 2022-01-28 8:05 ` Salvatore Filippone @ 2022-01-28 9:01 ` Paul Richard Thomas 0 siblings, 0 replies; 10+ messages in thread From: Paul Richard Thomas @ 2022-01-28 9:01 UTC (permalink / raw) To: Salvatore Filippone; +Cc: Jerry D, Andrew Benson, Damian Rouson, Fortran List Hi Salvatore, That's correct. It's what ifort does too. Thus far I have found only one or two minor niggles with the Intel implementation of finalization. Since, as often or not, the two compilers are frequently used by the same users, I will attempt to make them compliant with one another. I will have a conversation with the Intel developers sometime next week. BTW I noticed a small error in the patch that I attached last night. I introduced a kludge to fix your testcase in the call to gfc_copy_alloc_comp in finalize_function_result. The the expression rank is needed and has been introduced as a new argument to gfc_copy_alloc_comp. Ciao Paul On Fri, 28 Jan 2022 at 08:05, Salvatore Filippone < filippone.salvatore@gmail.com> wrote: > So, you are saying that three calls is the correct number, one for the > LHS, one for the RHS, and one for the deallocation in the main program. > I have (re)-read the standard, I would concur with your interpretation. > > On Thu, Jan 27, 2022 at 11:10 PM Paul Richard Thomas < > paul.richard.thomas@gmail.com> wrote: > >> Hi Salvatore, >> >> >> My reading of F2018: 7.5.6.3 "When finalization occurs" is that three >> calls is correct. (i) Paragraph 1 stipulates that the 'var' expression be >> evaluated before the reallocation and intrinsic assignment; (ii)stipulates >> that the function result be finalised "the result is finalized after >> execution of the innermost >> executable construct containing the reference." ; and (iii) Finalisation >> occurs on going out of scope. >> >> That is what is implemented in the attached. I am working my way through >> the testcase dependencies of PR37336 making sure that finalizat >> ion occurs as required by 7.5.6.3 and in the order defined in the >> previous section. It will all be done in the next few days. >> >> What will remain is finalization of function results within array >> constructors and one or two other corner cases. Following that, the >> existing finalization calls will be brought into the framework as the new >> calls. >> >> Best regards >> >> Paul >> >> >> On Thu, 27 Jan 2022 at 07:17, Salvatore Filippone < >> filippone.salvatore@gmail.com> wrote: >> >>> One more data point: Cray FTN issues TWO calls to the FINAL. >>> Which begs the question: what is the correct number of calls one, two or >>> three? >>> Salvatore >>> >>> fsalvato@daint102:/project/prce01/fsalvato/NUMERICAL/PSBLAS/V4/psblas4/test/newstuff> >>> ftn --version >>> Cray Fortran : Version 11.0.0 >>> fsalvato@daint102:/project/prce01/fsalvato/NUMERICAL/PSBLAS/V4/psblas4/test/newstuff> >>> ftn -o testfinal testfinal.f90 >>> fsalvato@daint102:/project/prce01/fsalvato/NUMERICAL/PSBLAS/V4/psblas4/test/newstuff> >>> ./testfinal >>> Allocating wrapper >>> Calling new_outer_type >>> Assigning outer%test_item >>> Called delete_test_type >>> End of new_outer_type >>> DeAllocating wrapper >>> Called delete_test_type >>> >>> On Wed, Jan 26, 2022 at 11:59 PM Paul Richard Thomas < >>> paul.richard.thomas@gmail.com> wrote: >>> >>>> Hi Jerry, >>>> >>>> I am trying to fix the failure of my latest patch with this very test >>>> case. Otherwise it fixes most of the remaining dependencies in PR37336. >>>> >>>> At a pinch, I could submit the earlier patch that Andrew mentions and >>>> work from there. However, you will note that it does miss one of the >>>> finalizations. This is critical because function results, which should be >>>> finalized, are not. >>>> >>>> I'll keep an eye on the state of the branch. By and large, release >>>> occurs 3-4 months after the start of stage 4. I will leave 2 months maximum. >>>> >>>> Best regards >>>> >>>> Paul >>>> >>>> >>>> On Wed, 26 Jan 2022 at 21:29, Jerry D via Fortran <fortran@gcc.gnu.org> >>>> wrote: >>>> >>>>> Is there any reason these patches can not be applied and use this test >>>>> as a test case? >>>>> >>>>> Regards, >>>>> >>>>> Jerry >>>>> >>>>> On 1/24/22 8:11 AM, Salvatore Filippone via Fortran wrote: >>>>> > Thanks a lot >>>>> > (yes, I suspected both gfortran and intel were wrong, precisely >>>>> because I >>>>> > could see why you'd need two FINAL calls, but not three). >>>>> > >>>>> > Salvatore >>>>> > >>>>> > On Mon, Jan 24, 2022 at 4:45 PM Andrew Benson < >>>>> abenson@carnegiescience.edu> >>>>> > wrote: >>>>> > >>>>> >> Hi Salvatore, >>>>> >> >>>>> >> This looks like it's related to some of the missing finalization >>>>> >> functionality >>>>> >> (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37336). Paul has some >>>>> >> patches >>>>> >> (e.g. >>>>> https://gcc.gnu.org/pipermail/fortran/2022-January/057415.html) >>>>> >> which >>>>> >> implement most of the missing functionality. With those patches >>>>> >> incorporated >>>>> >> your code gives the following output with gfortran: >>>>> >> >>>>> >> $ ./testfinal >>>>> >> Allocating wrapper >>>>> >> Calling new_outer_type >>>>> >> Assigning outer%test_item >>>>> >> Called delete_test_type >>>>> >> End of new_outer_type >>>>> >> DeAllocating wrapper >>>>> >> Called delete_test_type >>>>> >> >>>>> >> So there is one more call to the finalizer than you found - I >>>>> haven't >>>>> >> checked >>>>> >> carefully but I would guess this is a deallocation of LHS on >>>>> assignment. >>>>> >> >>>>> >> In testing these patches using the Intel compiler we found that it >>>>> seems >>>>> >> to >>>>> >> call the finalization wrapper more than it should, sometimes on >>>>> objects >>>>> >> that >>>>> >> have already been deallocated. Your code, compiled with the Intel >>>>> compiler >>>>> >> and >>>>> >> then run under valgrind shows the following: >>>>> >> >>>>> >> $ valgrind ./testfinal >>>>> >> ==7340== Memcheck, a memory error detector >>>>> >> ==7340== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward >>>>> et al. >>>>> >> ==7340== Using Valgrind-3.13.0 and LibVEX; rerun with -h for >>>>> copyright info >>>>> >> ==7340== Command: ./testfinal >>>>> >> ==7340== >>>>> >> ==7340== Conditional jump or move depends on uninitialised value(s) >>>>> >> ==7340== at 0x493A51: __intel_sse2_strcpy (in >>>>> /home/abensonca/Scratch/ >>>>> >> ifortTests/testfinal) >>>>> >> ==7340== by 0x45D70E: for__add_to_lf_table (in >>>>> /home/abensonca/Scratch/ >>>>> >> ifortTests/testfinal) >>>>> >> ==7340== by 0x4410CB: for__open_proc (in /home/abensonca/Scratch/ >>>>> >> ifortTests/testfinal) >>>>> >> ==7340== by 0x423A64: for__open_default (in >>>>> /home/abensonca/Scratch/ >>>>> >> ifortTests/testfinal) >>>>> >> ==7340== by 0x4305A9: for_write_seq_lis (in >>>>> /home/abensonca/Scratch/ >>>>> >> ifortTests/testfinal) >>>>> >> ==7340== by 0x4047E1: MAIN__ (testfinal.f90:62) >>>>> >> ==7340== by 0x403CE1: main (in >>>>> /home/abensonca/Scratch/ifortTests/ >>>>> >> testfinal) >>>>> >> ==7340== >>>>> >> Allocating wrapper >>>>> >> Calling new_outer_type >>>>> >> Assigning outer%test_item >>>>> >> Called delete_test_type >>>>> >> ==7340== Conditional jump or move depends on uninitialised value(s) >>>>> >> ==7340== at 0x40572A: do_alloc_copy (in >>>>> >> /home/abensonca/Scratch/ifortTests/ >>>>> >> testfinal) >>>>> >> ==7340== by 0x406B9A: do_alloc_copy (in >>>>> >> /home/abensonca/Scratch/ifortTests/ >>>>> >> testfinal) >>>>> >> ==7340== by 0x4084ED: for_alloc_assign_v2 (in >>>>> /home/abensonca/Scratch/ >>>>> >> ifortTests/testfinal) >>>>> >> ==7340== by 0x404474: target_mod_mp_new_outer_type_ >>>>> (testfinal.f90:48) >>>>> >> ==7340== by 0x40485E: MAIN__ (testfinal.f90:65) >>>>> >> ==7340== by 0x403CE1: main (in >>>>> /home/abensonca/Scratch/ifortTests/ >>>>> >> testfinal) >>>>> >> ==7340== >>>>> >> Called delete_test_type >>>>> >> End of new_outer_type >>>>> >> DeAllocating wrapper >>>>> >> Called delete_test_type >>>>> >> ==7340== >>>>> >> ==7340== HEAP SUMMARY: >>>>> >> ==7340== in use at exit: 48 bytes in 1 blocks >>>>> >> ==7340== total heap usage: 14 allocs, 13 frees, 12,879 bytes >>>>> allocated >>>>> >> ==7340== >>>>> >> ==7340== LEAK SUMMARY: >>>>> >> ==7340== definitely lost: 48 bytes in 1 blocks >>>>> >> ==7340== indirectly lost: 0 bytes in 0 blocks >>>>> >> ==7340== possibly lost: 0 bytes in 0 blocks >>>>> >> ==7340== still reachable: 0 bytes in 0 blocks >>>>> >> ==7340== suppressed: 0 bytes in 0 blocks >>>>> >> ==7340== Rerun with --leak-check=full to see details of leaked >>>>> memory >>>>> >> ==7340== >>>>> >> ==7340== For counts of detected and suppressed errors, rerun with: >>>>> -v >>>>> >> ==7340== Use --track-origins=yes to see where uninitialised values >>>>> come >>>>> >> from >>>>> >> ==7340== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 >>>>> from 0) >>>>> >> >>>>> >> so there are some cases of what look like incorrect accesses (and >>>>> some >>>>> >> leaked >>>>> >> memory). >>>>> >> >>>>> >> Your code compiled with gfortran (with Paul's patches in place) >>>>> shows no >>>>> >> errors or leaks from valgrind. >>>>> >> >>>>> >> So, in summary, in this case I think the current gfortran is >>>>> missing some >>>>> >> finalizations (which are fixed by Paul's patches), and ifort is >>>>> likely >>>>> >> doing >>>>> >> something wrong and probably calling the finalizer more times than >>>>> it >>>>> >> should. >>>>> >> >>>>> >> -Andrew >>>>> >> >>>>> >> On Monday, January 24, 2022 6:49:23 AM PST Salvatore Filippone via >>>>> Fortran >>>>> >> wrote: >>>>> >>> And here is the code embedded as text............ sorry about >>>>> sending an >>>>> >>> attachment that was purged >>>>> >>> ------------------------- testfinal.f90 --------------------- >>>>> >>> module test_type_mod >>>>> >>> >>>>> >>> type :: my_test_type >>>>> >>> integer, allocatable :: i >>>>> >>> contains >>>>> >>> final :: delete_test_type >>>>> >>> end type my_test_type >>>>> >>> >>>>> >>> interface my_test_type >>>>> >>> module procedure new_test_type_object >>>>> >>> end interface my_test_type >>>>> >>> >>>>> >>> contains >>>>> >>> >>>>> >>> subroutine delete_test_type(this) >>>>> >>> type(my_test_type) :: this >>>>> >>> >>>>> >>> write(*,*) 'Called delete_test_type' >>>>> >>> if (allocated(this%i)) deallocate(this%i) >>>>> >>> >>>>> >>> end subroutine delete_test_type >>>>> >>> >>>>> >>> >>>>> >>> function new_test_type_object(item) result(res) >>>>> >>> type(my_test_type) :: res >>>>> >>> integer, intent(in) :: item >>>>> >>> !Allocation on assignment >>>>> >>> res%i=item >>>>> >>> end function new_test_type_object >>>>> >>> >>>>> >>> >>>>> >>> end module test_type_mod >>>>> >>> >>>>> >>> module target_mod >>>>> >>> use test_type_mod >>>>> >>> type :: outer_type >>>>> >>> type(my_test_type), allocatable :: test_item >>>>> >>> end type outer_type >>>>> >>> >>>>> >>> contains >>>>> >>> >>>>> >>> subroutine new_outer_type(outer,item) >>>>> >>> type(outer_type), intent(out) :: outer >>>>> >>> integer :: item >>>>> >>> >>>>> >>> allocate(outer%test_item) >>>>> >>> write(*,*) 'Assigning outer%test_item' >>>>> >>> outer%test_item = my_test_type(itemi) >>>>> >>> write(*,*) 'End of new_outer_type' >>>>> >>> end subroutine new_outer_type >>>>> >>> >>>>> >>> end module target_mod >>>>> >>> >>>>> >>> program testfinal >>>>> >>> use target_mod >>>>> >>> >>>>> >>> implicit none >>>>> >>> >>>>> >>> integer :: i=10 >>>>> >>> type(outer_type), allocatable :: wrapper >>>>> >>> >>>>> >>> write(*,*) 'Allocating wrapper ' >>>>> >>> allocate(wrapper) >>>>> >>> write(*,*) 'Calling new_outer_type ' >>>>> >>> call new_outer_type(wrapper,i) >>>>> >>> write(*,*) 'DeAllocating wrapper ' >>>>> >>> deallocate(wrapper) >>>>> >>> >>>>> >>> end program testfinal >>>>> >>> >>>>> >>> On Mon, Jan 24, 2022 at 2:50 PM Salvatore Filippone < >>>>> >>> >>>>> >>> filippone.salvatore@gmail.com> wrote: >>>>> >>>> Hi all >>>>> >>>> The attached code compiles and runs fine under both GNU and >>>>> Intel, but >>>>> >> it >>>>> >>>> produces different results, in particular the FINAL subroutine is >>>>> >> invoked >>>>> >>>> just once with GNU, three times with Intel. >>>>> >>>> >>>>> >>>> It seems to me that they cannot both be right; I am not sure what >>>>> the >>>>> >>>> standard is mandating in this case. >>>>> >>>> Any ideas? >>>>> >>>> Salvatore >>>>> >>>> --------------- Intel >>>>> >>>> [pr1eio03@login1: newstuff]$ ifort -v >>>>> >>>> ifort version 19.1.1.217 >>>>> >>>> [pr1eio03@login1: newstuff]$ ifort -o testfinal testfinal.f90 >>>>> >>>> [pr1eio03@login1: newstuff]$ ./testfinal >>>>> >>>> >>>>> >>>> Allocating wrapper >>>>> >>>> Calling new_outer_type >>>>> >>>> Assigning outer%test_item >>>>> >>>> Called delete_test_type >>>>> >>>> Called delete_test_type >>>>> >>>> End of new_outer_type >>>>> >>>> DeAllocating wrapper >>>>> >>>> Called delete_test_type >>>>> >>>> >>>>> >>>> ----------------------------- GNU >>>>> >>>> sfilippo@lagrange newstuff]$ gfortran -v >>>>> >>>> Using built-in specs. >>>>> >>>> COLLECT_GCC=gfortran >>>>> >>>> >>>>> COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/11/lto-wrapper >>>>> >>>> OFFLOAD_TARGET_NAMES=nvptx-none >>>>> >>>> OFFLOAD_TARGET_DEFAULT=1 >>>>> >>>> Target: x86_64-redhat-linux >>>>> >>>> Configured with: ../configure --enable-bootstrap >>>>> >>>> --enable-languages=c,c++,fortran,objc,obj-c++,ada,go,d,lto >>>>> >> --prefix=/usr >>>>> >>>> --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl= >>>>> >>>> http://bugzilla.redhat.com/bugzilla --enable-shared >>>>> >>>> --enable-threads=posix --enable-checking=release --enable-multilib >>>>> >>>> --with-system-zlib --enable-__cxa_atexit >>>>> --disable-libunwind-exceptions >>>>> >>>> --enable-gnu-unique-object --enable-linker-build-id >>>>> >>>> --with-gcc-major-version-only --with-linker-hash-style=gnu >>>>> >> --enable-plugin >>>>> >>>> --enable-initfini-array >>>>> >>>> >>>>> >> >>>>> --with-isl=/builddir/build/BUILD/gcc-11.2.1-20210728/obj-x86_64-redhat-lin >>>>> >>>> ux/isl-install --enable-offload-targets=nvptx-none >>>>> >> --without-cuda-driver >>>>> >>>> --enable-gnu-indirect-function --enable-cet --with-tune=generic >>>>> >>>> --with-arch_32=i686 --build=x86_64-redhat-linux >>>>> >>>> Thread model: posix >>>>> >>>> Supported LTO compression algorithms: zlib zstd >>>>> >>>> gcc version 11.2.1 20210728 (Red Hat 11.2.1-1) (GCC) >>>>> >>>> [sfilippo@lagrange newstuff]$ gfortran -o testfinal testfinal.f90 >>>>> >>>> [sfilippo@lagrange newstuff]$ ./testfinal >>>>> >>>> >>>>> >>>> Allocating wrapper >>>>> >>>> Calling new_outer_type >>>>> >>>> Assigning outer%test_item >>>>> >>>> End of new_outer_type >>>>> >>>> DeAllocating wrapper >>>>> >>>> Called delete_test_type >>>>> >>>> >>>>> >>>> --------------------- >>>>> >> >>>>> >> -- >>>>> >> >>>>> >> * Andrew Benson: https://abensonca.github.io >>>>> >> >>>>> >> * Galacticus: https://github.com/galacticusorg/galacticus >>>>> >> >>>>> >> >>>>> >> >>>>> >> >>>>> >>>>> >>>> >>>> -- >>>> "If you can't explain it simply, you don't understand it well enough" - >>>> Albert Einstein >>>> >>> >> >> -- >> "If you can't explain it simply, you don't understand it well enough" - >> Albert Einstein >> > -- "If you can't explain it simply, you don't understand it well enough" - Albert Einstein ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2022-01-28 9:01 UTC | newest] Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2022-01-24 13:50 FINAL subroutines Salvatore Filippone 2022-01-24 14:49 ` Salvatore Filippone 2022-01-24 15:45 ` Andrew Benson 2022-01-24 16:11 ` Salvatore Filippone 2022-01-26 21:29 ` Jerry D 2022-01-26 22:59 ` Paul Richard Thomas 2022-01-27 7:17 ` Salvatore Filippone 2022-01-27 22:10 ` Paul Richard Thomas 2022-01-28 8:05 ` Salvatore Filippone 2022-01-28 9:01 ` Paul Richard Thomas
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).