https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118896
Bug ID: 118896 Summary: The fortran compiler is unable to devirtualize typebound indirect calls Product: gcc Version: 15.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: fortran Assignee: unassigned at gcc dot gnu.org Reporter: mikael at gcc dot gnu.org Target Milestone: --- With the following example (which is a simplified class_assign_4.f90 from the testsuite), I can see in the -O2 .optimized dump: <bb 4> [local count: 79480924]: ... _223 = MEM[(struct __vtype_m_T1 * {ref-all})&__vtab_m_T1]._copy; ... _223 (_231, _228); ... all this in the same basic block. The compiler should obviously be able to simplify the indirect call to a direct call, but it is unfortunately not the case. In this case the copy function is a simple integral copy, so devirtualizing and inlining the devirtualized function would have an important cascading effect to simplify the finally generated code. Testcase: module m implicit none type :: t1 integer :: i CONTAINS end type type, extends(t1) :: t2 real :: r end type end module m subroutine test_t1 use m implicit none class(t1), dimension(:), allocatable :: x, y x = [t1(3), t1(2), t1(1)] x = realloc_t1 (x) if (.not.check_t1 (x, [2,3,1], 1) ) stop 3 contains function realloc_t1 (arg) result (res) class(t1), dimension(:), allocatable :: arg class(t1), dimension(:), allocatable :: res select type (arg) type is (t2) allocate (res, source = [t1 (arg(3)%i), t1 (arg(2)%i), t1 (arg(1)%i)]) type is (t1) allocate (res, source = [t1 (arg(2)%i), t1 (arg(1)%i), t1 (arg(3)%i)]) end select end function realloc_t1 logical function check_t1 (arg, array, t, array2) class(t1) :: arg(:) integer :: array (:), t integer, optional :: array2(:) check_t1 = .true. select type (arg) type is (t1) if (any (arg%i .ne. array)) check_t1 = .false. if (t .eq. 2) check_t1 = .false. type is (t2) if (any (arg%i .ne. array)) check_t1 = .false. if (t .eq. 1) check_t1 = .false. if (present (array2)) then if (any(int (arg%r) .ne. array2)) check_t1 = .false. end if class default check_t1 = .false. end select end function check_t1 end subroutine test_t1 call test_t1 end