2016-03-29 12 views
-2

コンパイラが関数ポインタを介して呼び出しをインライン化できるかどうかを知りたかったのですが、関数ポインタによる呼び出しの最適化とインライン

gcc 4.8で-Osまたは-O2を指定してコンパイルすると、コンパイラはapply1とapply2をmainにインライン展開しますが、apply2の場合は関数ポインタ経由で間接呼び出しを削除しadd1コードもインクルードします。 apply1ではそうではありません。一般的には、私の関数静的宣言はその中でこの最適化を許しているようですが、静的ではありません。

これを説明する根本的な違いはありますか?

これは主に好奇心に溢れていますが、私が書く必要のある高性能コードに動機付けられているため、この違いを引き起こす可能性のあることを理解したいと考えています。

このコードはCですが、私はC++でも同じようにコンパイルしていますが、

#include <stdio.h> 

int add1(int a) 
{ 
    return a + 1; 
} 

void apply1(int lower, int upper, int (* func)(int)) 
{ 
    for (int i = lower; i < upper; i++) 
    { 
     printf("%d = %d\n", i, func(i)); 
    } 
} 

static void apply2(int lower, int upper, int (* func)(int)) 
{ 
    for (int i = lower; i < upper; i++) 
    { 
     printf("%d = %d\n", i, func(i)); 
    } 
} 

int main() 
{ 
    apply1(0, 10, add1); 
    apply2(0, 10, add1); 
} 
+0

アセンブリコードを見てください。 [funcへの間接呼び出しのオーバーヘッドがprintfのコストによって隠されるため、マイクロ最適化は役に立ちません。] –

+0

関数ポインタのインライン化は、LTOに関係する主要な機能の1つです。 – o11c

答えて

1

それは他のファイルとリンクされる場合APPLY1は、静的ではないのおかげで現在の翻訳単位外部ファイルに見え、おそらく翻訳単位外部から呼び出すことができます。そのため、funcパラメータにadd1以外の値を指定して呼び出すことができるため、最適化は無効になります。