試したソースはこれです。
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
こうなります。
色の付いたところが2箇所あるから一箇所にするというのが
-fcrossjumpingの最適化のようです。
volatile付けてるから
mov.B [r14], r4
は、共有されてほしくない。
しょうがないので、gccのソースを眺めてみました。
-fcrossjumpingの処理をしてるのは、cfgcleanup.cというのがわかりました。
色々試したみたところ、その中のold_insns_match_p関数でコードの比較をしています。
volatileなメモリの読み書きしている時の判定を追加します。
_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 1C bne .L5
0013 F0 E0 bset #0, [r14].B
0015 02 rts
.L5:
0016 F0 E8 bclr #0, [r14].B
0018 02 rts
共有部分が一行になり、自前のpeephole2の処理が機能するようになりました。
[0回]