> After some investigation, we discovered that this behavior is caused by > big hammer in gcc/cse.c: > /* A volatile ASM or an UNSPEC_VOLATILE invalidates everything. */ > if (NONJUMP_INSN_P (insn) > && volatile_insn_p (PATTERN (insn))) > flush_hash_table (); > This code (introduced in > http://gcc.gnu.org/viewcvs/gcc?view=revision&revision=193802) aborts CSE > after seeing a volatile inline asm.
Note that "introduced" is not really correct here, the code had been there for a long time but it was treating some volatile asms as barriers and some others as not. Now it treats them all as barriers. > Is this compiler behavior reasonable? AFAIK GCC documentation only says > that __volatile__ prevents compiler from removing the asm but it does > not mention that it supresses optimization of all surrounding expressions. This is not crystal clear, but the conservative interpretation is that you can use volatile asms to do really nasty things behind the back of the compiler: /* Nonzero if X contains any volatile instructions. These are instructions which may cause unpredictable machine state instructions, and thus no instructions or register uses should be moved or combined across them. This includes only volatile asms and UNSPEC_VOLATILE instructions. */ int volatile_insn_p (const_rtx x) > If this behavior is not intended, what would be the best way to fix > performance? I could teach GCC to not remove constant RTXs in > flush_hash_table() but this is probably very naive and won't cover some > corner-cases. That could be a good starting point though. -- Eric Botcazou