The svr4 ABI requires that r1 (SP) always be valid, so it must be restored at the end of the epilogue, after the last register restore read from the stack frame. Unfortunately, in some cases, the PPC port is scheduling the epilogue set of r1 before some register restores. If you take an interrupt in between the r1 set and a register restore, and the interrupt handler uses the process stack, the interrupt handler may overwrite saved registers before they can be restored. This causes difficult to debug failures.
I can reproduce the failure with -O2 -fno-omit-frame-pointer. I don't know if the problem can be triggered with other optimization options. The PPC port tries to prevent the r1 set from being moved before register restores by emitting a stack_tie instruction. This uses a BLKmode read from the stack frame, which in theory should conflict with the register reads and the set of r1. But this fails because of how reg_base_value works in alias.c. The PPC port is using a temp register r11 in the epilogue. In my testcase, r11 is set in the function body to the address of a variable in data. The code that sets reg_base_value, in init_alias_analysis in alias.c, deliberately ignores instructions in the prologue and epilogue. Thus it sees only one store to r11, and decides that r11 must hold a data variable address everywhere in the function. When we check stack reads (using r11) against the stack_tie insn (using r1), alias analysis decides that they can't conflict because r1 points to the stack and r11 points to data. Thus incorrect insn scheduling occurs. This seems to be a flaw in alias analysis. If we aren't going to count prologue/epilogue insns when computing reg_base_value, then we should not use reg_base_value when disambiguating insns in the prologue/epilogue. Unfortunately, the interface to alias is passing in only MEMs, not insns, so we can't easily tell when we have a prologue/epilogue MEM. A possible simple way to solve the problem is to use a stricter stack_tie insn. I noticed that the ARM port has one that uses (mem:BLK (scratch)). If I hack this into the rs6000 port, then this problem goes away. Testing for this is one of the first things that write_dependence_p does, so this prevents any possible reg_base_value confusion. This only fails if I get a symbol address into r11, and r11 is only set once, so it is a bit tricky to reproduce with small examples. I do have a testcase that works with gcc mainline which I will attach. -- Summary: bad epilogue scheduling leads to stack corruption Product: gcc Version: 4.5.0 Status: UNCONFIRMED Severity: major Priority: P3 Component: target AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: wilson at gcc dot gnu dot org GCC target triplet: powerpc-eabi http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42953