C++コンパイラ最適化
1、volatile:
2、NRV(Named Return Value)の最適化:
関数は、次のようなクラスを返します.
class X;X bar(){
}
コンパイラ実装://関数実装void bar(X&_result)/追加パラメータ{
}//関数呼び出しX x 2;//ここではメモリを予約するだけで、初期化関数bar(x 2)は呼び出されていません.
NRV最適化後:void bar(X&_result){
}
3、循環内変数の最適化:void test 2(char*s);void test(){ int i; for (i = 0; i < 10; i++) {
}}
アセンブリコード:movl$10,%ebxsubl$272,%esp#は272バイトスタック空間leal-264(%ebp),%esi#はbufアドレスをとる.L 2:movl%esi,(%esp)#bufアドレススタックcall test 2#呼び出しtest 2 subl$1,%ebxjne.L 2#ループが終了しない場合はL 2へジャンプ
この関数ではbufはループごとに生成されるのではなく,ループ外生成であり,ループ内で絶えず使用される.
4、算数式最適化a*2はa+aにコンパイルされる.符号なし数a/2はa>>1にコンパイルされる.符号数a/2がある.
5、memset関数最適化memset関数は常に大きなメモリを初期化するために使用されますが、小さなデータにとってmemsetは十分に効率的に維持できますか?このプログラムを見てください.
アセンブリにコンパイル:movl$0,-24(%ebp)#s 1 movl$0,-20(%ebp)movl$0,-16(%ebp)movl$0,-12(%ebp)call test 2#呼び出しtest 2 leal-82216(%ebp),%edx#設定s 2 xorl%eax,%eaxmovl%edx,%edimovl$2048,%ecxrep sstomovl%edx,(%esp)#呼び出しtest 2 calltest 2 calltest 2 movl%ebx,%ebx%ebx,%edimovl%ebx,%edimovl$2048,%ecxrexrep s,(% esp)#s 3 movl$8193,8(%esp)movl$0,4(%esp)call memsetmovl%ebx,(%esp)#呼び出しtest 2 call test 2データ長が比較的小さい場合(例えばs 1が16バイト)、memsetは連続的な付与文にコンパイルされる.データ長が8 KB以下の場合(例えばs 2)、memsetはシリアル操作命令で実現される.データ長が8 KBより大きい場合(s 3など)、memsetは関数呼び出しにコンパイルされる.
シリアル・オペレーション・クラス・コマンド:メモリの1つのストレージ領域に複数のバイト(またはワード)データが連続的に格納されます.このようなデータのセットを「データ列」(高度な言語では配列とみなされます).各データが1バイトである場合、「バイト列」と呼ばれます.字なら「文字列」と呼ぶ.シリアル・オペレーション・コマンドは、メモリ領域のデータ・シリアル・オペレーションを実現するために使用することができる.シリアル操作命令は、毎回、データ列のうちの1つのデータのみを処理するが、重複接頭辞と組み合わせて(重複接頭辞+シリアル操作命令)使用すると、操作を繰り返すことができる(その実行過程は1つのループプログラムの実行に相当し、重複回数はレジスタCXによって決定される).
:volatile , , , , 、 、 。
: volatile , 。 , , , memory- barriers。
:volatile , , , 。
2、NRV(Named Return Value)の最適化:
関数は、次のようなクラスを返します.
class X;X bar(){
X x1;
// x1..
return x1;
}
コンパイラ実装://関数実装void bar(X&_result)/追加パラメータ{
// x1
X x1;
// ,
x1.X::X();
// x1..
//
__result.X::X(x1);
return;
}//関数呼び出しX x 2;//ここではメモリを予約するだけで、初期化関数bar(x 2)は呼び出されていません.
NRV最適化後:void bar(X&_result){
// __result
__result.X::X();
// __result
return;
}
3、循環内変数の最適化:void test 2(char*s);void test(){ int i; for (i = 0; i < 10; i++) {
char buf[256];
test2(buf); // test2 buf ,
}}
アセンブリコード:movl$10,%ebxsubl$272,%esp#は272バイトスタック空間leal-264(%ebp),%esi#はbufアドレスをとる.L 2:movl%esi,(%esp)#bufアドレススタックcall test 2#呼び出しtest 2 subl$1,%ebxjne.L 2#ループが終了しない場合はL 2へジャンプ
この関数ではbufはループごとに生成されるのではなく,ループ外生成であり,ループ内で絶えず使用される.
4、算数式最適化a*2はa+aにコンパイルされる.符号なし数a/2はa>>1にコンパイルされる.符号数a/2がある.
5、memset関数最適化memset関数は常に大きなメモリを初期化するために使用されますが、小さなデータにとってmemsetは十分に効率的に維持できますか?このプログラムを見てください.
アセンブリにコンパイル:movl$0,-24(%ebp)#s 1 movl$0,-20(%ebp)movl$0,-16(%ebp)movl$0,-12(%ebp)call test 2#呼び出しtest 2 leal-82216(%ebp),%edx#設定s 2 xorl%eax,%eaxmovl%edx,%edimovl$2048,%ecxrep sstomovl%edx,(%esp)#呼び出しtest 2 calltest 2 calltest 2 movl%ebx,%ebx%ebx,%edimovl%ebx,%edimovl$2048,%ecxrexrep s,(% esp)#s 3 movl$8193,8(%esp)movl$0,4(%esp)call memsetmovl%ebx,(%esp)#呼び出しtest 2 call test 2データ長が比較的小さい場合(例えばs 1が16バイト)、memsetは連続的な付与文にコンパイルされる.データ長が8 KB以下の場合(例えばs 2)、memsetはシリアル操作命令で実現される.データ長が8 KBより大きい場合(s 3など)、memsetは関数呼び出しにコンパイルされる.
シリアル・オペレーション・クラス・コマンド:メモリの1つのストレージ領域に複数のバイト(またはワード)データが連続的に格納されます.このようなデータのセットを「データ列」(高度な言語では配列とみなされます).各データが1バイトである場合、「バイト列」と呼ばれます.字なら「文字列」と呼ぶ.シリアル・オペレーション・コマンドは、メモリ領域のデータ・シリアル・オペレーションを実現するために使用することができる.シリアル操作命令は、毎回、データ列のうちの1つのデータのみを処理するが、重複接頭辞と組み合わせて(重複接頭辞+シリアル操作命令)使用すると、操作を繰り返すことができる(その実行過程は1つのループプログラムの実行に相当し、重複回数はレジスタCXによって決定される).