在C++中,通常會將可能內聯到頭文件中的小函數放在可能的內聯中,而無需藉助鏈接時優化或其他巫術。大多數情況下,對於類的訪問器方法(請參閱std::vector
上的operator[]
)。我在現代Fortran中遇到了一些類似的行爲。派生類型訪問函數的跨模塊內聯
說我有一個定義派生類型與一些私有數據,用一個簡單的存取這樣的模塊:
module FooMod
type :: FooType
integer,allocatable,private :: d(:)
contains
procedure,pass :: init
procedure,pass :: get
procedure,pass :: clear
endtype
contains
subroutine init(this,n)
class(FooType),intent(inout) :: this
integer,intent(in) :: n
integer :: i
allocate(this%d(n))
do i=1,n
this%d(i)=i
enddo
endsubroutine
function get(this,i) result(val)
class(FooType),intent(in) :: this
integer,intent(in) :: i
integer :: val
val = this%d(i)
endfunction
subroutine clear(this)
class(FooType),intent(inout) :: this
deallocate(this%d)
endsubroutine
endmodule
現在我寫一個程序使用訪問:
program testtype
use FooMod
type(FooType) :: foo
integer :: val
call foo%init(10)
val = foo%get(2)
write(*,*)val
endprogram
用gfortran編譯5.4.0用-O3
:
gfortran -c -O3 foo.f90
gfortran -O3 -S testfoo.f90 foo.o
產生輸出像這樣:
call __foomod_MOD_get
leaq 16(%rsp), %rdi
movl %eax, 12(%rsp)
movq $.LC2, 24(%rsp)
movl $11, 32(%rsp)
movl $128, 16(%rsp)
movl $6, 20(%rsp)
call _gfortran_st_write
所以仍然有一個調用發生,沒有內聯。我知道,因爲get()
例程的定義位於不同的翻譯單元中,因此與C++標題的文本相比可能有點困難,但我認爲這是.mod
文件生成的目的的一部分編譯器。
有沒有什麼辦法讓這樣的小功能跨模塊內聯?如果沒有,在數據封裝的現代編程實踐中,這似乎是語言/實現方面的嚴重缺陷。
我試着-flto
標誌來看看這是否會有所幫助,但只是吐出GIMPLE ascii文本字段到「程序集」輸出,所以很難說出它在做什麼。
謝謝!一些澄清:我知道C++中的inline
,它的真正含義,它有點不恰當,並且非常熟悉內聯的概念;它是如何工作的,需要滿足哪些條件,爲什麼沒有標題很難,以及LTO適合於圖片。我的主要挫折是,由於Fortran有正式的模塊,編譯器允許編譯器生成實現特定的.mod文件,爲什麼這麼困難呢?爲什麼我們需要明確地使用語言不可知的鏈接時間(困難)內聯的大槍來做一些簡單的內聯類型綁定存取器函數。編譯器能否存儲GIMPLE代碼,甚至是.mod文件中的函數文本,並執行編譯時內聯?也許我錯過了一些微妙之處。
你使用了哪些編譯器選項? '-flto'確實是完全必要的,它是在不同的文件中編譯的,使用不同的gfortran調用。 –
您可能需要查看與'-flto' [此處](https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html)相關的文檔來記錄一些可能有助於您的相關選項調查(例如'-fno-fat-lto-objects')。請注意,'-flto'必須在編譯和鏈接階段提供。 –
另外[相關問題](https://stackoverflow.com/a/42386798) –