This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


Hi!

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?

2007-07-18  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_set): On sibcall alloc insn set copy_state to
	need_copy_state.
	(process_for_unwind_directive): Emit .copy_state at the
	start of bb if copy_state is need_copy_state.  On return_internal
	insn set copy_state to need_copy_state if it was label_state_emitted
	before.

	* gcc.dg/pr32338.c: New test.

--- gcc/config/ia64/ia64.c.jj	2007-07-04 19:06:50.000000000 -0400
+++ gcc/config/ia64/ia64.c	2007-07-18 18:21:20.000000000 -0400
@@ -2885,6 +2885,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
@@ -2916,6 +2925,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) 
     {
@@ -8744,10 +8755,6 @@ ia64_in_small_data_p (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
@@ -8811,7 +8818,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)
@@ -8857,6 +8865,11 @@ process_set (FILE *asm_out_file, rtx pat
 	  if (current_frame_info.total_size == 0 && !frame_pointer_needed)
 	    /* if haven't done process_epilogue() yet, do it now */
 	    process_epilogue (asm_out_file, insn, unwind, frame);
+	  if (!last_block)
+	    {
+	      gcc_assert (copy_state == label_state_emitted);
+	      copy_state = need_copy_state;
+	    }
 	  if (unwind)
 	    fprintf (asm_out_file, "\t.prologue\n");
 	}
@@ -9076,7 +9089,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)
 		{
@@ -9086,10 +9099,17 @@ 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 (GET_CODE (insn) == JUMP_INSN
+	  && copy_state == label_state_emitted
+	  && GET_CODE (PATTERN (insn)) == PARALLEL
+	  && XVECLEN (PATTERN (insn), 0) == 2
+	  && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == RETURN)
+	copy_state = need_copy_state;
+
       if (GET_CODE (insn) == NOTE || ! RTX_FRAME_RELATED_P (insn))
 	return;
 
--- gcc/testsuite/gcc.dg/pr32338.c	2007-06-19 15:57:27.463462805 +0200
+++ gcc/testsuite/gcc.dg/pr32338.c	2007-07-16 19:33:11.000000000 +0200
@@ -0,0 +1,41 @@
+/* PR target/32338 */
+/* { dg-do link } */
+/* { dg-options "-O2 -fno-omit-frame-pointer" } */
+
+struct S
+{
+};
+
+int foo (struct S *d)
+{
+  return 2;
+}
+
+int bar (struct S *d)
+{
+  return 4;
+}
+
+int 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;
+}

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]