https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59401
--- Comment #5 from Oleg Endo <olegendo at gcc dot gnu.org> --- Ugh, there's actually another problem with this thing, I think: void other (void); int test0 (void) { int x = ((int*)__builtin_thread_pointer ())[2]; other (); return ((int*)__builtin_thread_pointer ())[5] + x; } compiles to: stc gbr,r8 mov.l .L3,r1 jsr @r1 mov.l @(8,r8),r9 mov.l @(20,r8),r0 << use GBR value before the call add r9,r0 lds.l @r15+,pr mov.l @r15+,r9 rts mov.l @r15+,r8 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.