diff options
author | Jakub Jelinek <jakub@redhat.com> | 2010-05-26 08:00:44 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2010-05-26 08:00:44 +0200 |
commit | 0d65bdbb703d5da86f2987aadd735049db9c2af0 (patch) | |
tree | dd65d1e614fa43328db8f1be183bb7801199c86b /gcc | |
parent | cc9a4ca9331ad603c930616c7d5700b5b56dc82b (diff) | |
download | gcc-0d65bdbb703d5da86f2987aadd735049db9c2af0.zip gcc-0d65bdbb703d5da86f2987aadd735049db9c2af0.tar.gz gcc-0d65bdbb703d5da86f2987aadd735049db9c2af0.tar.bz2 |
re PR target/44199 (ppc64 glibc miscompilation)
PR target/44199
* config/rs6000/rs6000.c (rs6000_emit_epilogue): If cfun->calls_alloca
or total_size is larger than red zone size for non-V4 ABI, emit a
stack_tie resp. frame_tie insn before stack pointer restore.
* config/rs6000/rs6000.md (frame_tie): New insn.
From-SVN: r159853
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 18 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.md | 9 |
3 files changed, 35 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ed93893..abcdeae 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2010-05-26 Jakub Jelinek <jakub@redhat.com> + + PR target/44199 + * config/rs6000/rs6000.c (rs6000_emit_epilogue): If cfun->calls_alloca + or total_size is larger than red zone size for non-V4 ABI, emit a + stack_tie resp. frame_tie insn before stack pointer restore. + * config/rs6000/rs6000.md (frame_tie): New insn. + 2010-05-25 Eric Botcazou <ebotcazou@adacore.com> * function.h (struct function): Add can_throw_non_call_exceptions bit. diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 35be57b..eb8af6f 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -19796,6 +19796,16 @@ rs6000_emit_epilogue (int sibcall) frame_reg_rtx = sp_reg_rtx; if (DEFAULT_ABI == ABI_V4) frame_reg_rtx = gen_rtx_REG (Pmode, 11); + /* Prevent reordering memory accesses against stack pointer restore. */ + else if (cfun->calls_alloca + || offset_below_red_zone_p (-info->total_size)) + { + rtx mem1 = gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx); + rtx mem2 = gen_rtx_MEM (BLKmode, sp_reg_rtx); + MEM_NOTRAP_P (mem1) = 1; + MEM_NOTRAP_P (mem2) = 1; + emit_insn (gen_frame_tie (mem1, mem2)); + } insn = emit_insn (gen_add3_insn (frame_reg_rtx, hard_frame_pointer_rtx, GEN_INT (info->total_size))); @@ -19805,6 +19815,14 @@ rs6000_emit_epilogue (int sibcall) && DEFAULT_ABI != ABI_V4 && !crtl->calls_eh_return) { + /* Prevent reordering memory accesses against stack pointer restore. */ + if (cfun->calls_alloca + || offset_below_red_zone_p (-info->total_size)) + { + rtx mem = gen_rtx_MEM (BLKmode, sp_reg_rtx); + MEM_NOTRAP_P (mem) = 1; + emit_insn (gen_stack_tie (mem)); + } insn = emit_insn (gen_add3_insn (sp_reg_rtx, sp_reg_rtx, GEN_INT (info->total_size))); sp_offset = 0; diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 73eca19..34d619c 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -15286,6 +15286,15 @@ "" [(set_attr "length" "0")]) +; Like stack_tie, but depend on both fp and sp based memory. +(define_insn "frame_tie" + [(set (match_operand:BLK 0 "memory_operand" "+m") + (unspec:BLK [(match_dup 0) + (match_operand:BLK 1 "memory_operand" "m")] UNSPEC_TIE))] + "" + "" + [(set_attr "length" "0")]) + (define_expand "epilogue" [(use (const_int 0))] |