------- Comment #1 from jakub at gcc dot gnu dot org 2007-10-02 13:38 ------- Simplified testcase which also fails on x86_64-linux:
/* PR tree-optimization/33619 */ /* { dg-do run } */ /* { dg-options "-O2" } */ #ifdef __powerpc__ # define REG1 "3" # define REG2 "4" #elif defined __x86_64__ # define REG1 "rdi" # define REG2 "rsi" #endif static inline void bar (unsigned long x, int y) { register unsigned long p1 __asm__ (REG1) = x; register unsigned long p2 __asm__ (REG2) = y; __asm__ volatile ("" : "=r" (p1), "=r" (p2) : "0" (p1), "1" (p2) : "memory"); if (p1 != 0xdeadUL || p2 != 0xbefUL) __builtin_abort (); } __attribute__((const, noinline)) int baz (int x) { return x; } __attribute__((noinline)) void foo (unsigned long *x, int y) { unsigned long a = *x; bar (a, baz (y)); } int main (void) { unsigned long a = 0xdeadUL; foo (&a, 0xbefUL); return 0; } In the presence of DECL_HARD_REGISTER vars making any kind of calls, even when they are const or pure, replaceable is IMHO wrong. Does it buy us anything to make any calls replaceable (i.e. what would we lose by simply if (get_call_expr_in (stmt)) return false; in is_replaceable_p)? If yes, we either need to disallow them if the current BB ever sets or uses any DECL_HARD_REGISTER vars, or need to do analysis if the replacement in rewrite_trees crosses any such sets or uses. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33619