rx-elf-gccでvolatileつけた変数の参照、変更した時のコードを覗いてみました。
試したソースはこれです。
volatile
unsigned
char bar1;
volatile
unsigned
char bar;
void
tst_bar_bit0(void)
{
if(bar1&1)
bar &= ~1;
else
bar |= 1;
}
rx-elf-gccで-O2 -fomitframe-pointerでコンパイルすると
_tst_bar_bit0:
0000 FB E2 00 00 00 00 mov.L #_bar1, r14
0006 CC EE mov.B [r14], r14
0008 FD 74 CE 01 tst #1, r14
000c FB E2 00 00 00 00 mov.L #_bar, r14
0012 CC E4 mov.B [r14], r4
0014 1E bne .L5
0015 65 14 or #1, r4
0017 C3 E4 mov.B r4, [r14]
0019 02 rts
.L5:
001a 75 24 FE and #-2, r4
001d C3 E4 mov.B r4, [r14]
001f 02 rts
こうなります。
volatileつけた変数を参照、変更してるから、最適化は無効になってるのかと思いきや、最適化されてます。
で、巷でよく聞くメモリバリアというのをソースに埋め込んでみました。
void
tst_bar_bit0(void)
{
if(bar1&1)
{
__asm volatile (";memory1":::"memory");
bar &= ~1;
}
else
{
__asm volatile (";memory2":::"memory");
bar |= 1;
}
}
_tst_bar_bit0:
0000 FB E2 00 00 00 00 mov.L #_bar1, r14
0006 CC EE mov.B [r14], r14
0008 FD 74 CE 01 tst #1, r14
000c 1A bne .L5
; 32 "tst1b.c" 1
;memory2
; 0 "" 2
000d FB E2 00 00 00 00 mov.L #_bar, r14
0013 F0 E0 bset #0, [r14].B
0015 02 rts
.L5:
; 27 "tst1b.c" 1
;memory1
; 0 "" 2
0016 FB E2 00 00 00 00 mov.L #_bar, r14
001c F0 E8 bclr #0, [r14].B
001e 02 rts
今度は期待した通りのコードになっています。
分岐を最適化するオプション-fcrossjumpingというのがあるので
それを無効にするように-fno-crossjumpingで元々のソースをコンパイルすると
0000 FB E2 00 00 00 00 mov.L #_bar1, r14
0006 CC EE mov.B [r14], r14
0008 FD 74 CE 01 tst #1, r14
000c 1A bne .L5
000d FB E2 00 00 00 00 mov.L #_bar, r14
0013 F0 E0 bset #0, [r14].B
0015 02 rts
.L5:
0016 FB E2 00 00 00 00 mov.L #_bar, r14
001c F0 E8 bclr #0, [r14].B
001e 02 rts
こうなりました。
(素のgccのソースでビルドしたgccではbset,bclrのコードは出ませんので)
volatile付けると最適化抑止になると思いきや、こういうことがあるんですね。
archによっては、-fcrossjumpingが無効になってるものもあるようです。
ちなみに、mips-elf-gccだとこうなりました。
0000 93820000 lbu $2,%gp_rel(bar1)($28)
0004 00000000 nop
0008 30420001 andi $2,$2,0x1
000c 14400008 bne $2,$0,$L5
0010 00000000 nop
0014 93820000 lbu $2,%gp_rel(bar)($28)
0018 00000000 nop
001c 304200FF andi $2,$2,0x00ff
0020 34420001 ori $2,$2,0x1
0024 A3820000 sb $2,%gp_rel(bar)($28)
0028 03E00008 j $31
002c 00000000 nop
$L5:
0030 93820000 lbu $2,%gp_rel(bar)($28)
0034 00000000 nop
0038 304200FE andi $2,$2,0xfe
003c A3820000 sb $2,%gp_rel(bar)($28)
0040 03E00008 j $31
0044 00000000 nop
[0回]
PR