11.1 volatile修飾子

volatile修飾子をつけて変数宣言すると,その変数は最適化の対象から外され,レジスタに割り付ける最適化などを行わなくなります。volatile指定された変数に対する操作を行うときは,必ずメモリから値を読み込み,操作後にメモリへ値を書き込むコードになります。また,volatile指定された変数のアクセス幅も変更されません。

volatile指定されていない変数は,最適化によってレジスタに割り付けられ,その変数をメモリからロードするコードが削除されることがあります。また,volatile指定されていない変数に同じ値を代入する場合,冗長な命令と解釈されて最適化により命令が削除されることもあります。特に周辺I/Oレジスタへアクセスする変数や,割り込み処理で値が変更される変数,また,外部から値が変更される変数に対しては,volatile指定する必要があります。

volatile指定すべきところで指定されていなかった場合,次の現象が起こることがあります。

-

正しい計算結果が得られない

-

ループ内で変数を使っていた場合,ループから抜け出せない

-

命令の実行順序が変わる

-

メモリのアクセス回数・アクセス幅が変わる

 

ただし,volatile指定した変数を使用する際,ある区間でその変数の値が外部から変更されないことが自明な場合,volatile指定されていない変数に,その値を代入してその変数を参照することにより,その変数が最適化され,実行速度が向上する可能性があります。

 

【volatile指定しなかった場合のソースと出力コードの例】

“変数a”,“変数b”,および“変数c”をvolatile指定しなかった場合,これらの変数がレジスタに割り付けられ,最適化されます。たとえば,この間に割り込みが入り,割り込み内で変数値を変更しても,値が反映されないことになります。

int a;
int b;
void func(void){
    if(a <= 0){
        b++;
    } else {
        b+=2;
    }
    b++;
}
 
 
 
 
 
 
 
_func:
        MOVHI   HIGHW1(#_a), R0, R6
        LD.W    LOWW(#_a)[R6], R6
        CMP     0x00000000, R6
        MOVHI   HIGHW1(#_b), R0, R6
        LD.W    LOWW(#_b)[R6], R6
        BGT     .BB1_2          ; bb3
.BB1_1:     ; bb1
        ADD     0x00000001, R6
        BR      .BB1_3          ; bb9
.BB1_2:     ; bb3
        ADD     0x00000002, R6
.BB1_3:     ; bb9
        ADD     0x00000001, R6
        MOVHI   HIGHW1(#_b), R0, R7
        ST.W    R6, LOWW(#_b)[R7]
        JMP     [R31]

 

【volatile指定した場合のソースと出力コードの例】

“変数a”,“変数b”,および“変数c”をvolatile指定した場合,これらの変数値を必ずメモリから読み込み,操作後にメモリへ書き込むコードが出力されます。たとえば,この間に割り込みが入り,割り込み内で変数値が変更されても,その変更が反映された結果を取得することができます(このような例の場合,割り込みのタイミングによっては,変数の操作区間内を割り込み禁止にするなどの処置が必要となります)。

volatile指定をすると,メモリの読み込み/書き込み処理が入るため,volatile指定しなかった場合よりもコード・サイズは大きくなります。

volatile int a;
volatile int b;
void func(void){
    if(a <= 0){
        b++;
    } else {
        b+=2;
    }
    b++;
}
 
 
 
 
 
 
 
 
 
 
 
_func:
        MOVHI   HIGHW1(#_a), R0, R6
        LD.W    LOWW(#_a)[R6], R6
        CMP     0x00000000, R6
        BGT     .BB1_2          ; bb3
.BB1_1:    ; bb1
        MOVHI   HIGHW1(#_b), R0, R6
        LD.W    LOWW(#_b)[R6], R6
        ADD     0x00000001, R6
        BR      .BB1_3          ; bb9
.BB1_2:    ; bb3
        MOVHI   HIGHW1(#_b), R0, R6
        LD.W    LOWW(#_b)[R6], R6
        ADD     0x00000002, R6
.BB1_3:    ; bb9
        MOVHI   HIGHW1(#_b), R0, R7
        ST.W    R6, LOWW(#_b)[R7]
        LD.W    LOWW(#_b)[R7], R6
        ADD     0x00000001, R6
        ST.W    R6, LOWW(#_b)[R7]
        JMP     [R31]