https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59401
--- Comment #6 from Oleg Endo <olegendo at gcc dot gnu.org> --- (In reply to Oleg Endo from comment #5) > Ugh, there's actually another problem with this thing, I think: > > ... > > By default, GBR is marked as call-clobbered. Currently, if the GBR mem > optimization thing sees any calls in a function it will not form the GBR > address. It's not optimal, but was supposed to produce at least correct > code. Obviously the code above is wrong. The __builtin_thread_pointer insn > is hoisted by something else before combine/split1. The patch from r216128 > is incomplete. I'm checking it out. No, hoisting __builtin_thread_pointer is OK. It only makes the following impossible to do: void foo (void* otherthread) { ... access current thread's context ... switch_thread (otherthread); ... access otherthread's context ... } The compiler doesn't know that switch_thread modifies the thread pointer. One workaround is: switch_thread (otherthread); void* newtp; __asm__ __volatile__ ("stc gbr, %0" : "=r" (newtp)); __builtin_set_thread_pointer (newtp); However, this is just a hypothetical use case. I don't think there is an immediate use for that. Usually the thread pointer is not switched like that in the middle of a function, probably not even when implementing cooperative threading/fibers. Thus I think it would make sense to change the default behavior from GBR call clobbered to GBR call preserved. Actually making GBR call preserved is the only way for the GBR mem access optimization to make any sense because otherwise it will never form GBR mems if calls are present in a function, which defeats its purpose. It would be possible to make a better analysis of when GBR is used (before / after calls etc), but I think it's worth it in this case. Kaz, what's your opinion on making GBR to be call preserved by default?