volatileによる最適化の回避

最適化とは

コンパイラがソースプログラムから実行形式を作成するときにおこなう作業の一つで、一般には以下の様なものがある。

  1. 実行形式を可能な限り小さくする。(プログラムサイズの最適化)
  2. 実行形式のプログラムが、可能な限り高速に動作するようにする。(実行速度の最適化)

  コンパイラは最適化を行わない場合、通常はソースプログラムで記述された内容をそのまま実行形式に変換する。最適化オプションを有効にすると、プログラマが意図していない(ソースプログラムの記述とは異なる)実行形式が作成される事がある。
 たとえば、こんなプログラムがあったとする。

#include < machine.h >
#include "monitor.h"

int main()
{
     int   i;

    i = 1;
    printf("test\n");
    return 0;
}

 まったく意味の無いプログラムではある。(特に変数iって必要? ....と人が思うということは、コンパイラも同じように考えるということ)
 結果として、コンパイラは上のプログラムを最適化して、以下のように解釈して実行形式を作成する。

#include < machine.h >
#include "monitor.h"

int main()
{
      printf("test\n");
      return 0;
}

普通はこれでも問題無いのであるが、ハードウエアに設定を行うような操作では問題が生じる。たとえば、以下のプログラムでは、

#include < machine.h >
#include "monitor.h"

#define PB_DDR (*(unsigned char *)0xFFFD4)  // アドレス0xFFFD4へのポインタを定義

int main()
{
      PB_DDR = 0xFF; // ① 最適化によってこの行が消去される。
      printf("test\n");
      return 0;
}

最適化の結果、①の行が削除されてしまう。このような事態を避けたい場合に型宣言の前にvolatileを付加することで最適化を回避する。
 



【最適化の実例】

以下のプログラムで、最適化がどのように動作するか、機械語命令で比較してみると、

#include "monitor.h"
int main()
{
    volatile int c = 0;  // 最適化を抑止

    while (1)
    {
        c++;
    }
    return 0;
}


(1) volatileあり (変数cの最適化を抑止)



(2) votatileなし (変数cの最適化を実行)



(1)と(2)を比較すれば分かるように、最適化を行うことで変数cに関連した処理が消滅している。通常、このような動作は有り難い事が多いのだが、ハードウエア制御では「余計なお世話」になることも多いので、十分注意する事。
 

最終更新:2014年03月28日 15:35