aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2010-05-26 08:00:44 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2010-05-26 08:00:44 +0200
commit0d65bdbb703d5da86f2987aadd735049db9c2af0 (patch)
treedd65d1e614fa43328db8f1be183bb7801199c86b /gcc
parentcc9a4ca9331ad603c930616c7d5700b5b56dc82b (diff)
downloadgcc-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/ChangeLog8
-rw-r--r--gcc/config/rs6000/rs6000.c18
-rw-r--r--gcc/config/rs6000/rs6000.md9
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))]