[PATCH] Fix ia64 .copy_state/.body directive emission (PR target/32338, take 2)

Jakub Jelinek jakub@redhat.com
Wed Sep 5 09:50:00 GMT 2007


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



More information about the Gcc-patches mailing list