volatileとgcc

追加した機能が元で最適化の問題をを踏んだ。
何故か呼ばれるはずの関数が飛ばされるので何でかと思ったら
volatileつけ忘れが原因。


どの程度最適化掛けると飛ばされるようになるのか気になったのでサンプル書いて実験。
踏んだプログラムはthread使ってたけど、スコープ外で変更掛かるから同じだろうと
思いサンプルは単純化


テストコード

int flag_g;

int main(int argc,char ** argv){
        flag_g = 0;

        if(flag_g)
                printf("HOGE\n");

        return 0;
}

int func(){
        flag_g = 1;
}

gcc -O0 の objdump

000103dc <main>:
   103dc:       9d e3 bf 98     save  %sp, -104, %sp
   103e0:       f0 27 a0 44     st  %i0, [ %fp + 0x44 ]
   103e4:       f2 27 a0 48     st  %i1, [ %fp + 0x48 ]
   103e8:       03 00 00 81     sethi  %hi(0x20400), %g1
   103ec:       82 10 62 ec     or  %g1, 0x2ec, %g1     ! 206ec <flag_g>
   103f0:       c0 20 40 00     clr  [ %g1 ]
   103f4:       03 00 00 81     sethi  %hi(0x20400), %g1
   103f8:       82 10 62 ec     or  %g1, 0x2ec, %g1     ! 206ec <flag_g>
   103fc:       c2 00 40 00     ld  [ %g1 ], %g1
   10400:       80 a0 60 00     cmp  %g1, 0
   10404:       02 80 00 06     be  1041c <main+0x40>
   10408:       01 00 00 00     nop
   1040c:       03 00 00 41     sethi  %hi(0x10400), %g1
   10410:       90 10 61 90     or  %g1, 0x190, %o0     ! 10590 <_IO_stdin_used+0x8>
   10414:       40 00 40 af     call  206d0 <printf@plt>
   10418:       01 00 00 00     nop
   1041c:       82 10 20 00     clr  %g1        ! 0 <_init-0x10284>
   10420:       b0 10 00 01     mov  %g1, %i0
   10424:       81 c7 e0 08     ret
   10428:       81 e8 00 00     restore

gcc -O1 の objdump

000103b4 <main>:
   103b4:       03 00 00 81     sethi  %hi(0x20400), %g1
   103b8:       c0 20 62 58     clr  [ %g1 + 0x258 ]    ! 20658 <flag_g>
   103bc:       81 c3 e0 08     retl
   103c0:       90 10 20 00     clr  %o0

gcc -O1 の objdump (flag_gにvolatile付与)

000103ec <main>:
   103ec:       9d e3 bf 98     save  %sp, -104, %sp
   103f0:       05 00 00 81     sethi  %hi(0x20400), %g2
   103f4:       c0 20 a2 dc     clr  [ %g2 + 0x2dc ]    ! 206dc <flag_g>
   103f8:       c6 00 a2 dc     ld  [ %g2 + 0x2dc ], %g3
   103fc:       80 a0 e0 00     cmp  %g3, 0
   10400:       02 80 00 05     be  10414 <main+0x28>
   10404:       b0 10 20 00     clr  %i0
   10408:       03 00 00 41     sethi  %hi(0x10400), %g1
   1040c:       40 00 40 aa     call  206b4 <puts@plt>
   10410:       90 10 61 78     or  %g1, 0x178, %o0     ! 10578 <_IO_stdin_used+0x8>
   10414:       81 c7 e0 08     ret
   10418:       81 e8 00 00     restore

gcc -O1の時点で既に関数呼び出し箇所が跡形もなくなっている。


今回問題追っかけていて使ったけど、gdbのtuiモードは意外に便利だった。
registerとassemblerウィンドウ出しながらステップ実行とか。