diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index af05fca5d5ed41d5e609c08ab9c8ef5294a3b945..d16c38c8c1559e9171422f8fee6ff3731dc3568a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2007-09-12  Jakub Jelinek  <jakub@redhat.com>
+
+	PR target/32338
+	* config/ia64/ia64.c (ia64_expand_epilogue): Emit blockage
+	before sp restoration even when total_size is 0, but
+	frame_pointer_needed.
+
 2007-09-12  Bob Wilson  <bob.wilson@acm.org>
 
 	* config/xtensa/xtensa.c (machine_function): Add vararg_a7_copy.
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index 46f75c5a205c73fe00271f4de6da9c6851d3ce5e..6a6a9e62f0c99013d787363bd0a14c189fc2c60a 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -3437,7 +3437,9 @@ ia64_expand_epilogue (int sibcall_p)
 
   finish_spill_pointers ();
 
-  if (current_frame_info.total_size || cfun->machine->ia64_eh_epilogue_sp)
+  if (current_frame_info.total_size
+      || cfun->machine->ia64_eh_epilogue_sp
+      || frame_pointer_needed)
     {
       /* ??? At this point we must generate a magic insn that appears to
          modify the spill iterators, the stack pointer, and the frame
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 433471cd1d3f9a60a06ec10fdd6a51db40828545..977c2a50eed2560690b0b9365adafe6870b6b7e7 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2007-09-12  Jakub Jelinek  <jakub@redhat.com>
+
+	PR target/32338
+	* gcc.dg/pr32338-1.c: New test.
+	* gcc.dg/pr32338-2.c: New test.
+
 2007-09-12  Bob Wilson  <bob.wilson@acm.org>
 	
 	* lib/target-supports.exp (check_effective_target_sync_int_long):
diff --git a/gcc/testsuite/gcc.dg/pr32338-1.c b/gcc/testsuite/gcc.dg/pr32338-1.c
new file mode 100644
index 0000000000000000000000000000000000000000..6a79a8c228152e4f2645db5461e06b9bc1313d30
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr32338-1.c
@@ -0,0 +1,47 @@
+/* PR target/32338 */
+/* { dg-do link } */
+/* { dg-options "-O2 -fno-omit-frame-pointer" } */
+
+struct S
+{
+};
+
+int
+__attribute__((noinline))
+foo (struct S *d)
+{
+  return 2;
+}
+
+int
+__attribute__((noinline))
+bar (struct S *d)
+{
+  return 4;
+}
+
+int
+__attribute__((noinline))
+fnl (char const *q)
+{
+  return __builtin_strlen (q);
+}
+
+int
+__attribute__((noinline))
+baz (struct S *d, char const *q)
+{
+  unsigned int len;
+  len = fnl (q);
+  if (len > 512)
+    return bar (d);
+  return foo (d);
+}
+
+int
+main (int argc, char *argv[])
+{
+  if (argc > 30)
+    return baz ((void *) 0, "abcde");
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr32338-2.c b/gcc/testsuite/gcc.dg/pr32338-2.c
new file mode 100644
index 0000000000000000000000000000000000000000..81daddf6a67af0f3fc36528935585562f4ec18b9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr32338-2.c
@@ -0,0 +1,47 @@
+/* PR target/32338 */
+/* { dg-do link } */
+/* { dg-options "-O2 -fno-omit-frame-pointer" } */
+
+struct S
+{
+};
+
+int
+__attribute__((noinline))
+foo (void)
+{
+  return 2;
+}
+
+int
+__attribute__((noinline))
+bar (void)
+{
+  return 4;
+}
+
+int
+__attribute__((noinline))
+fnl (void)
+{
+  return 6;
+}
+
+int
+__attribute__((noinline))
+baz (void)
+{
+  unsigned int len;
+  len = fnl ();
+  if (len > 512)
+    return bar ();
+  return foo ();
+}
+
+int
+main (int argc, char *argv[])
+{
+  if (argc > 30)
+    return baz ();
+  return 0;
+}