This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix ia64 .copy_state/.body directive emission (PR target/32338, take 2)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Jim Wilson <wilson at specifix dot com>
- Date: Wed, 5 Sep 2007 05:50:37 -0400
- Subject: [PATCH] Fix ia64 .copy_state/.body directive emission (PR target/32338, take 2)
- References: <20070719071640.GH2063@devserv.devel.redhat.com>
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
On Thu, Jul 19, 2007 at 03:16:40AM -0400, Jakub Jelinek wrote:
> The dataflow changes allow (set (r12) (...)) RTX_FRAME_RELATEX_P
> instructions in ia64 epilogues and sibcall epilogues to be moved
> more freely within the EBBs, but .copy_state handling in ia64.c
> relied on those insns always staying in BB where they were originally
> emitted during prologue/epilogue threading.
> Either we can prevent such moves with blockage insn (as already done
> for current_frame_info.total_size != 0 functions), patches for that
> attached to bugzilla, or we can accept that sched2 can move those
> instructions inside their EBBs as well (as done in the following patch).
> Bootstrapped/regtested on ia64-linux, ok for trunk?
During a bootstrap last night that version of the patch showed problems
during libjava build, when
current_frame_info.n_input_regs == 0
no alloc insn is created before the tail call and so .body and .copy_state
wasn't emitted where it should.
The following patch doesn't have that problem, bootstrapped/regtested
on ia64-linux, ok for trunk?
2007-09-05 Jakub Jelinek <jakub@redhat.com>
PR target/32338
* config/ia64/ia64.c (copy_state): New variable.
(ia64_expand_prologue): Set copy_state to no_copy_state.
(need_copy_state): Removed.
(process_epilogue): Set copy_state to label_state_emitted.
(process_for_unwind_directive): Emit .copy_state at the
start of bb if copy_state is need_copy_state. On return_internal
or SIBLING_CALL_P insn set copy_state to need_copy_state if it was
label_state_emitted before.
* gcc.dg/pr32338-1.c: New test.
* gcc.dg/pr32338-2.c: New test.
--- gcc/config/ia64/ia64.c.jj 2007-08-25 09:06:46.000000000 +0200
+++ gcc/config/ia64/ia64.c 2007-09-05 08:35:40.000000000 +0200
@@ -2873,6 +2873,15 @@ gen_fr_restore_x (rtx dest, rtx src, rtx
return gen_fr_restore (dest, src);
}
+/* States for .label_state/.copy_state handling. */
+
+static enum
+{
+ no_copy_state,
+ label_state_emitted,
+ need_copy_state
+} copy_state;
+
/* Called after register allocation to add any instructions needed for the
prologue. Using a prologue insn is favored compared to putting all of the
instructions in output_function_prologue(), since it allows the scheduler
@@ -2904,6 +2913,8 @@ ia64_expand_prologue (void)
ia64_compute_frame_size (get_frame_size ());
last_scratch_gr_reg = 15;
+ gcc_assert (copy_state != need_copy_state);
+ copy_state = no_copy_state;
if (dump_file)
{
@@ -8758,10 +8769,6 @@ ia64_in_small_data_p (const_tree exp)
static bool last_block;
-/* True if we need a copy_state command at the start of the next block. */
-
-static bool need_copy_state;
-
#ifndef MAX_ARTIFICIAL_LABEL_BYTES
# define MAX_ARTIFICIAL_LABEL_BYTES 30
#endif
@@ -8825,7 +8832,8 @@ process_epilogue (FILE *asm_out_file, rt
if (unwind)
fprintf (asm_out_file, "\t.label_state %d\n",
++cfun->machine->state_num);
- need_copy_state = true;
+ gcc_assert (copy_state == no_copy_state);
+ copy_state = label_state_emitted;
}
if (unwind)
@@ -9090,7 +9098,7 @@ process_for_unwind_directive (FILE *asm_
last_block = NOTE_BASIC_BLOCK (insn)->next_bb == EXIT_BLOCK_PTR;
/* Restore unwind state from immediately before the epilogue. */
- if (need_copy_state)
+ if (copy_state == need_copy_state)
{
if (unwind)
{
@@ -9100,10 +9108,21 @@ process_for_unwind_directive (FILE *asm_
}
if (IA64_CHANGE_CFA_IN_EPILOGUE && frame)
ia64_dwarf2out_def_steady_cfa (insn);
- need_copy_state = false;
+ copy_state = no_copy_state;
}
}
+ if (copy_state == label_state_emitted)
+ {
+ if (JUMP_P (insn)
+ && GET_CODE (PATTERN (insn)) == PARALLEL
+ && XVECLEN (PATTERN (insn), 0) == 2
+ && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == RETURN)
+ copy_state = need_copy_state;
+ else if (CALL_P (insn) && SIBLING_CALL_P (insn))
+ copy_state = need_copy_state;
+ }
+
if (GET_CODE (insn) == NOTE || ! RTX_FRAME_RELATED_P (insn))
return;
--- gcc/testsuite/gcc.dg/pr32338-1.c.jj 2007-09-05 08:39:37.000000000 +0200
+++ gcc/testsuite/gcc.dg/pr32338-1.c 2007-09-05 08:06:29.000000000 +0200
@@ -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;
+}
--- gcc/testsuite/gcc.dg/pr32338-2.c.jj 2007-09-05 08:39:43.000000000 +0200
+++ gcc/testsuite/gcc.dg/pr32338-2.c 2007-09-05 08:28:25.000000000 +0200
@@ -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;
+}
Jakub