C++コンパイラ最適化


1、volatile:
   :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によって決定される).